<!DOCTYPE html>
<html>

<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
	<meta name="theme-color" content="#33474d">
	<title>失落的乐章</title>
	<link rel="stylesheet" href="/css/style.css" />
	
      <link rel="alternate" href="/atom.xml" title="失落的乐章" type="application/atom+xml">
    
</head>

<body>

	<header class="header">
		<nav class="header__nav">
			
				<a href="/archives" class="header__link">Archive</a>
			
				<a href="/tags" class="header__link">Tags</a>
			
				<a href="/atom.xml" class="header__link">RSS</a>
			
		</nav>
		<h1 class="header__title"><a href="/">失落的乐章</a></h1>
		<h2 class="header__subtitle">技术面前，永远都是学生。</h2>
	</header>

	<main>
		
	<span class="different-posts different-posts_earlier">📖 <a href="/page/17">earlier posts</a> 📖</span>




	<article>
	
		<h1><a href="/2017/10/12/Redis/15. 征服 Redis/">征服 Redis</a></h1>
	
	<div class="article__infos">
		<span class="article__date">2017-10-12</span><br />
		
		
			<span class="article__tags">
			  	<a class="article__tag-link" href="/tags/Redis/">Redis</a>
			</span>
		
	</div>

	

	
		<h2 id="一、Redis简要介绍"><a href="#一、Redis简要介绍" class="headerlink" title="一、Redis简要介绍"></a>一、Redis简要介绍</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<strong>Redis</strong> —— <strong>RE</strong>mote <strong>DI</strong>ctionary <strong>S</strong>erver，可以直接理解为远程字典服务，也就是基于Key-Value模式Memcached+Database Persistence。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;如果真要把Redis与Memcached进行对比，参考下图：</p>
<p><figure class="figure"><img src="https://github.com/hcldirgit/image/blob/master/%E5%BE%81%E6%9C%8DRedis/01%20-%20%E5%89%AF%E6%9C%AC.jpeg?raw=true" alt=""></figure></p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;使用Memcached，让我感触颇深的是Object Size的问题，由于SQL未作优化直接映射对象，导致缓存对象大于1MB，Memcached就抛了异常。而Redis默认缓存对象512MB，最大支持1GB。至少在缓存对象时，可以有更大的伸缩空间了！</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;此外，是数据类型。Memcached比较简单，而Redis可以支持更多复杂的数据类型，如HASH、SET、SortedSet等等。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<strong>PS:Memcached</strong>是在<strong>Server端</strong>实现的<strong>Sharding</strong>，<strong>Redis</strong>没有对应的实现，据说3.0系列开始支持。</p>
<h2 id="二、安装"><a href="#二、安装" class="headerlink" title="二、安装"></a>二、安装</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis装起来，实在是过于简单，让我几乎“无从下手”。因为连“configure”文件都不需要，你只需要做个“make”就好。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在这里<a href="https://code.google.com/archive/p/redis/downloads" target="_blank" rel="external">下载Redis最新版</a>，这里用Redis 2.4.16</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;下载&amp;解压：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">wget http://redis.googlecode.com/files/redis-2.4.16.tar.gz  </div><div class="line">tar zxvf redis-2.4.16.tar.gz</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis可以解压至任何目录，一个make安装即可获得执行、配置文件。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;安装（这里将redis解压到/opt/目录下）：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">cd</span> /opt/redis-2.4.16  </div><div class="line">make</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;make之后，我们会得到以下可执行文件：</p>
<ul>
<li><strong>redis-server</strong>：Redis服务器的daemon启动程序</li>
<li><strong>redis-cli</strong>：Redis命令行操作工具。或者通过telnet进行纯文本协议操作</li>
<li><strong>redis-benchmark</strong>：Redis性能测试工具，测试Redis在你的系统及你的配置下的读写性能</li>
</ul>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;上述文件位于src目录下。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;我习惯性的执行了make install，貌似我需要的可执行文件，安装到了/usr/local/bin：</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;引用</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div></pre></td><td class="code"><pre><div class="line">make install</div><div class="line"><span class="built_in">cd</span> src &amp;&amp; make install</div><div class="line">make[1]: Entering directory `/opt/software/redis-2.4.16/src<span class="string">'</span></div><div class="line"><span class="string">MAKE hiredis</span></div><div class="line"><span class="string">make[2]: Entering directory `/opt/software/redis-2.4.16/deps/hiredis'</span></div><div class="line">make[2]: Nothing to be <span class="keyword">done</span> <span class="keyword">for</span> `static<span class="string">'.</span></div><div class="line"><span class="string">make[2]: Leaving directory `/opt/software/redis-2.4.16/deps/hiredis'</span></div><div class="line">MAKE linenoise</div><div class="line">make[2]: Entering directory `/opt/software/redis-2.4.16/deps/linenoise<span class="string">'</span></div><div class="line"><span class="string">make[2]: “linenoise_example”是最新的。</span></div><div class="line"><span class="string">make[2]: Leaving directory `/opt/software/redis-2.4.16/deps/linenoise'</span></div><div class="line">MAKE hiredis</div><div class="line">make[2]: Entering directory `/opt/software/redis-2.4.16/deps/hiredis<span class="string">'</span></div><div class="line"><span class="string">make[2]: Nothing to be done for `static'</span>.</div><div class="line">make[2]: Leaving directory `/opt/software/redis-2.4.16/deps/hiredis<span class="string">'</span></div><div class="line"><span class="string">    LINK redis-benchmark</span></div><div class="line"><span class="string">    LINK redis-cli</span></div><div class="line"><span class="string"></span></div><div class="line"><span class="string">Hint: To run '</span>make <span class="built_in">test</span><span class="string">' is a good idea ;)</span></div><div class="line"><span class="string"></span></div><div class="line"><span class="string">mkdir -p /usr/local/bin</span></div><div class="line"><span class="string">cp -pf redis-server /usr/local/bin</span></div><div class="line"><span class="string">cp -pf redis-benchmark /usr/local/bin</span></div><div class="line"><span class="string">cp -pf redis-cli /usr/local/bin</span></div><div class="line"><span class="string">cp -pf redis-check-dump /usr/local/bin</span></div><div class="line"><span class="string">cp -pf redis-check-aof /usr/local/bin</span></div><div class="line"><span class="string">make[1]: Leaving directory `/opt/software/redis-2.4.16/src'</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;这样，就不用我拷贝文件了。意外收获！</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;此外，还会得到一个默认的配置文件——redis.conf。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;最好，把它拷贝到固定的目录下，例如：/etc/redis/目录下！</p>
<ol>
<li>mkdir /etc/redis  </li>
<li>cp redis.conf /etc/redis     </li>
</ol>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;然后，我们就可以在任何路径下，直接启动Redis了！</p>
<h2 id="三、运行"><a href="#三、运行" class="headerlink" title="三、运行"></a>三、运行</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;运行Redis：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">redis-server /etc/redis/redis.conf</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;引用</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">[1958] 13 Aug 16:18:24 * Server started, Redis version 2.4.16</div><div class="line">[1958] 13 Aug 16:18:24 <span class="comment"># WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.</span></div><div class="line">[1958] 13 Aug 16:18:24 * The server is now ready to accept connections on port 6379</div><div class="line">[1958] 13 Aug 16:18:24 - 0 clients connected (0 slaves), 717544 bytes <span class="keyword">in</span> use</div></pre></td></tr></table></figure>
<h2 id="四、测试"><a href="#四、测试" class="headerlink" title="四、测试"></a>四、测试</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;通过客户端命令<strong>redis-cli</strong>访问Redis</p>
<h3 id="引用"><a href="#引用" class="headerlink" title="引用"></a>引用</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># redis-cli  </span></div><div class="line">    redis&gt; <span class="built_in">set</span> name zlex  </div><div class="line">    OK  </div><div class="line">    redis&gt; get name   </div><div class="line">    <span class="string">"zlex"</span> </div><div class="line">``` </div><div class="line"></div><div class="line">&amp;<span class="comment">#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;进行数据测试：</span></div><div class="line"></div><div class="line">```bash</div><div class="line">redis-benchmark -l</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;这个测试会一直进行下去，直到你Ctrl+C：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div></pre></td><td class="code"><pre><div class="line">====== PING (inline) ======</div><div class="line">10000 requests completed <span class="keyword">in</span> 0.12 seconds</div><div class="line">50 parallel clients</div><div class="line">3 bytes payload</div><div class="line">keep alive: 1</div><div class="line"></div><div class="line">99.31% &lt;= 1 milliseconds</div><div class="line">99.53% &lt;= 2 milliseconds</div><div class="line">99.64% &lt;= 3 milliseconds</div><div class="line">99.70% &lt;= 4 milliseconds</div><div class="line">99.74% &lt;= 5 milliseconds</div><div class="line">99.78% &lt;= 6 milliseconds</div><div class="line">99.82% &lt;= 7 milliseconds</div><div class="line">99.84% &lt;= 8 milliseconds</div><div class="line">99.86% &lt;= 9 milliseconds</div><div class="line">99.89% &lt;= 10 milliseconds</div><div class="line">99.91% &lt;= 11 milliseconds</div><div class="line">99.93% &lt;= 12 milliseconds</div><div class="line">99.96% &lt;= 13 milliseconds</div><div class="line">99.98% &lt;= 14 milliseconds</div><div class="line">100.00% &lt;= 15 milliseconds</div><div class="line">81300.81 requests per second</div><div class="line"></div><div class="line">====== PING ======</div><div class="line">10000 requests completed <span class="keyword">in</span> 0.12 seconds</div><div class="line">50 parallel clients</div><div class="line">3 bytes payload</div><div class="line">keep alive: 1</div><div class="line"></div><div class="line">99.96% &lt;= 1 milliseconds</div><div class="line">100.00% &lt;= 1 milliseconds</div><div class="line">84033.61 requests per second</div><div class="line"></div><div class="line">^CET (10 keys): 26200.00</div></pre></td></tr></table></figure>
<h2 id="五、关闭"><a href="#五、关闭" class="headerlink" title="五、关闭"></a>五、关闭</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;也可通过客户端命令<strong>redis-cli</strong>完成<strong>Redis</strong>关闭操作:</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">redis-cli shutdown</div></pre></td></tr></table></figure>
<h3 id="引用-1"><a href="#引用-1" class="headerlink" title="引用"></a>引用</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line">[2639] 13 Aug 16:35:35 <span class="comment"># User requested shutdown...</span></div><div class="line">[2639] 13 Aug 16:35:35 * Saving the final RDB snapshot before exiting.</div><div class="line">[2639] 13 Aug 16:36:49 * DB saved on disk</div><div class="line">[2639] 13 Aug 16:36:49 <span class="comment"># Redis is now ready to exit, bye bye...</span></div><div class="line">``` </div><div class="line"></div><div class="line"><span class="comment">## 六、调优</span></div><div class="line"><span class="comment">### 1./etc/sysctl.conf</span></div><div class="line">&amp;<span class="comment">#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;前面启动Redis时，看到如下警告：</span></div><div class="line"></div><div class="line"><span class="comment">### 引用</span></div><div class="line"></div><div class="line">```bash</div><div class="line">[1958] 13 Aug 16:18:24 <span class="comment"># WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;需要修改<strong>/etc/sysctl.conf</strong>文件：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">vim /etc/sysctl.conf</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;末尾追加<strong>vm.overcommit_memory = 1</strong></p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;然后执行<strong>sysctl vm.overcommit_memory=1</strong>，使之生效：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">sysctl vm.overcommit_memory=1  </div><div class="line">vm.overcommit_memory = 1</div></pre></td></tr></table></figure>
<h3 id="2-proc-sys-vm-overcommit-memory"><a href="#2-proc-sys-vm-overcommit-memory" class="headerlink" title="2./proc/sys/vm/overcommit_memory"></a>2./proc/sys/vm/overcommit_memory</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;为了调整内存分配策略，需要配置<strong>/proc/sys/vm/overcommit_memory</strong></p>
<ul>
<li>0， 表示内核将检查是否有足够的可用内存供应用进程使用；如果有足够的可用内存，内存申请允许；否则，内存申请失败，并把错误返回给应用进程。</li>
<li>1， 表示内核允许分配所有的物理内存，而不管当前的内存状态如何。</li>
<li>2， 表示内核允许分配超过所有物理内存和交换空间总和的内存</li>
</ul>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;默认为0，如果内存情况比较紧张的话，设为1：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">echo</span> 1 &gt; /proc/sys/vm/overcommit_memory</div></pre></td></tr></table></figure>
<h3 id="3-redis-conf"><a href="#3-redis-conf" class="headerlink" title="3.redis.conf"></a>3.redis.conf</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;前面启动Redis后，总是在命令行里不断跳着各种日志，很麻烦。即便通过“&amp;”，领其后台运行，也无济于事。这就需要修改<strong>redis.conf</strong>，以Daemo模式运行！</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<strong>redis.conf</strong>参数：</p>
<ul>
<li>daemonize：是否以后台daemon方式运行</li>
<li>pidfile：pid文件位置</li>
<li>port：监听的端口号</li>
<li>timeout：请求超时时间</li>
<li>loglevel：log信息级别</li>
<li>logfile：log文件位置</li>
<li>databases：开启数据库的数量</li>
<li>save <em> </em>：保存快照的频率，第一个<em>表示多长时间（秒级），第三个</em>表示执行多少次写操作。在一定时间内执行一定数量的写操作时，自动保存快照。可设置多个条件。</li>
<li>rdbcompression：是否使用压缩</li>
<li>dbfilename：数据快照文件名（只是文件名，不包括目录）</li>
<li>dir：数据快照的保存目录（这个是目录）</li>
<li>appendonly：是否开启appendonlylog，开启的话每次写操作会记一条log，这会提高数据抗风险能力，但影响效率。</li>
<li>appendfsync：appendonlylog如何同步到磁盘（三个选项，分别是每次写都强制调用fsync、每秒启用一次fsync、不调用fsync等待系统自己同步）</li>
<li>slaveof <masterip> <masterport> ：主从配置，在redis-slave上配置master的ip port，即可。</masterport></masterip></li>
</ul>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;例如，我们可以修改为如下方式：</p>
<h4 id="引用-2"><a href="#引用-2" class="headerlink" title="引用"></a>引用</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">daemonize yes <span class="comment">#守护进程模式</span></div><div class="line">save 60 1000 <span class="comment">#当时间间隔超过60秒，或存储超过1000条记录时，进行持久化。</span></div><div class="line">maxmemory 256mb <span class="comment">#分配256MB内存</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<strong>PS：切记，一定要设定maxmemmory，且配置大小要小于物理内存，留有足够的内存供系统使用。</strong></p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;公司一同学的Redis，某期间数据暴涨，导致内存吃紧，SWAP加剧，直接宕机。就是因为没有设置<strong>maxmemmory</strong>。</p>
<h2 id="七、集群配置"><a href="#七、集群配置" class="headerlink" title="七、集群配置"></a>七、集群配置</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;把鸡蛋都放在一个篮子里是件危险的事情。首先，要做好主备。其次，如果可以做一致性哈希，可以起到负载均衡的作用。</p>
<p><figure class="figure"><img src="https://github.com/hcldirgit/image/blob/master/%E5%BE%81%E6%9C%8DRedis/02%20-%20%E5%89%AF%E6%9C%AC.png?raw=true" alt=""></figure></p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;配置Master-Slave，只需要在Slave上配置Master节点IP Port： </p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;这里的Master IP 为192.168.133.139 端口位6379，配置redis.conf：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">slaveof 192.168.133.139 6379</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<strong>PS：为了两个Redis Server可以互访，需要注释掉bind 127.0.0.1</strong></p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;依次启动Master，Slave：</p>
<h4 id="Master"><a href="#Master" class="headerlink" title="Master"></a>Master</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div></pre></td><td class="code"><pre><div class="line">[7651] 17 Aug 19:08:07 * Server started, Redis version 2.4.16</div><div class="line">[7651] 17 Aug 19:08:07 * DB loaded from disk: 0 seconds</div><div class="line">[7651] 17 Aug 19:08:07 * The server is now ready to accept connections on port 6379</div><div class="line">[7651] 17 Aug 19:08:08 * Slave ask <span class="keyword">for</span> synchronization</div><div class="line">[7651] 17 Aug 19:08:08 * Starting BGSAVE <span class="keyword">for</span> SYNC</div><div class="line">[7651] 17 Aug 19:08:08 * Background saving started by pid 7652</div><div class="line">[7652] 17 Aug 19:08:08 * DB saved on disk</div><div class="line">[7651] 17 Aug 19:08:08 * Background saving terminated with success</div><div class="line">[7651] 17 Aug 19:08:08 * Synchronization with slave succeeded</div><div class="line">``` </div><div class="line"> </div><div class="line"><span class="comment">#### Slave</span></div><div class="line"></div><div class="line">```bash</div><div class="line">[7572] 17 Aug 19:07:39 * Server started, Redis version 2.4.16</div><div class="line">[7572] 17 Aug 19:07:39 * DB loaded from disk: 0 seconds</div><div class="line">[7572] 17 Aug 19:07:39 * The server is now ready to accept connections on port 6379</div><div class="line">[7572] 17 Aug 19:07:39 * Connecting to MASTER...</div><div class="line">[7572] 17 Aug 19:08:08 * MASTER &lt;-&gt; SLAVE sync started: SYNC sent</div><div class="line">[7572] 17 Aug 19:08:08 * MASTER &lt;-&gt; SLAVE sync: receiving 10 bytes from master</div><div class="line">[7572] 17 Aug 19:08:08 * MASTER &lt;-&gt; SLAVE sync: Loading DB <span class="keyword">in</span> memory</div><div class="line">[7572] 17 Aug 19:08:08 * MASTER &lt;-&gt; SLAVE sync: Finished with success</div><div class="line">``` </div><div class="line"></div><div class="line">&amp;<span class="comment">#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;看到上述日志，就说明Master-Slave已经连通。</span></div><div class="line"> </div><div class="line"></div><div class="line">&amp;<span class="comment">#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;简单测试，Master写，Slave读：</span></div><div class="line"> </div><div class="line"><span class="comment">#### Master写</span></div><div class="line"></div><div class="line">```bash</div><div class="line">telnet 192.168.133.139 6379</div><div class="line">Trying 192.168.133.139...</div><div class="line">Connected to 192.168.133.139.</div><div class="line">Escape character is <span class="string">'^]'</span>.</div><div class="line"><span class="built_in">set</span> name snowolf</div><div class="line">+OK</div><div class="line">``` </div><div class="line"> </div><div class="line"><span class="comment">#### Slave读 </span></div><div class="line"></div><div class="line">```bash</div><div class="line">telnet 192.168.133.140 6379</div><div class="line">Trying 192.168.133.140...</div><div class="line">Connected to 192.168.133.140.</div><div class="line">Escape character is <span class="string">'^]'</span>.</div><div class="line">get name</div><div class="line"><span class="variable">$7</span></div><div class="line">snowolf</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;搞定！</p>
<h2 id="八、主从备份"><a href="#八、主从备份" class="headerlink" title="八、主从备份"></a>八、主从备份</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在从服务器上执行下列命令：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="comment">#备份  </span></div><div class="line">redis-cli save  </div><div class="line"></div><div class="line"><span class="comment">#关闭redis服务器  </span></div><div class="line">redis-cli shutdown</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;然后，拷贝数据目录下的rdb文件。</p>
<h2 id="九、系统服务"><a href="#九、系统服务" class="headerlink" title="九、系统服务"></a>九、系统服务</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;习惯了通过service启动一切服务，当然，这跟我生产环境部署有关，通常只分配给用于部署的账户操作service命令的权限。主要是为了确保系统安全。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;参考之前写的Memcached的系统服务文件，改造一个Redis版本！</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;新建文件，并赋予权限： </p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div><div class="line">92</div><div class="line">93</div><div class="line">94</div><div class="line">95</div><div class="line">96</div><div class="line">97</div></pre></td><td class="code"><pre><div class="line">touch /etc/init.d/redis-server  </div><div class="line">chmod +x /etc/init.d/redis-server  </div><div class="line">``` </div><div class="line"></div><div class="line">&amp;<span class="comment">#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;编辑**/etc/init.d/redis-server**，键入如下内容： </span></div><div class="line"></div><div class="line">```bash</div><div class="line"><span class="meta">#!/bin/bash  </span></div><div class="line"><span class="comment">#  </span></div><div class="line"><span class="comment"># redis    Startup script for redis processes  </span></div><div class="line"><span class="comment">#  </span></div><div class="line"><span class="comment"># author: snowolf  </span></div><div class="line"><span class="comment">#  </span></div><div class="line"><span class="comment"># processname: redis  </span></div><div class="line"></div><div class="line">redis_path=<span class="string">"/usr/local/bin/redis-server"</span>  </div><div class="line">redis_conf=<span class="string">"/etc/redis/redis.conf"</span>  </div><div class="line">redis_pid=<span class="string">"/var/run/redis.pid"</span>  </div><div class="line"></div><div class="line"><span class="comment"># Source function library.  </span></div><div class="line">. /etc/rc.d/init.d/<span class="built_in">functions</span>  </div><div class="line"></div><div class="line">[ -x <span class="variable">$redis_path</span> ] || <span class="built_in">exit</span> 0  </div><div class="line"></div><div class="line">RETVAL=0  </div><div class="line">prog=<span class="string">"redis"</span>  </div><div class="line"></div><div class="line"></div><div class="line"><span class="comment"># Start daemons.  </span></div><div class="line"><span class="function"><span class="title">start</span></span>() &#123;  </div><div class="line">    <span class="keyword">if</span> [ -e <span class="variable">$redis_pid</span> -a ! -z <span class="variable">$redis_pid</span> ];<span class="keyword">then</span>  </div><div class="line">        <span class="built_in">echo</span> <span class="variable">$prog</span><span class="string">" already running...."</span>  </div><div class="line">        <span class="built_in">exit</span> 1  </div><div class="line">    <span class="keyword">fi</span>  </div><div class="line">    </div><div class="line">    <span class="built_in">echo</span> -n $<span class="string">"Starting <span class="variable">$prog</span> "</span>  </div><div class="line">    <span class="comment"># Single instance for all caches  </span></div><div class="line">    <span class="variable">$redis_path</span> <span class="variable">$redis_conf</span>  </div><div class="line">    RETVAL=$?  </div><div class="line">    [ <span class="variable">$RETVAL</span> -eq 0 ] &amp;&amp; &#123;  </div><div class="line">        touch /var/lock/subsys/<span class="variable">$prog</span>  </div><div class="line">        success $<span class="string">"<span class="variable">$prog</span>"</span>  </div><div class="line">    &#125;  </div><div class="line">    <span class="built_in">echo</span>  </div><div class="line">    <span class="built_in">return</span> <span class="variable">$RETVAL</span>  </div><div class="line">&#125;  </div><div class="line"></div><div class="line"></div><div class="line"><span class="comment"># Stop daemons.  </span></div><div class="line"><span class="function"><span class="title">stop</span></span>() &#123;  </div><div class="line">    <span class="built_in">echo</span> -n $<span class="string">"Stopping <span class="variable">$prog</span> "</span>  </div><div class="line">    killproc -d 10 <span class="variable">$redis_path</span>  </div><div class="line">    <span class="built_in">echo</span>  </div><div class="line">    [ <span class="variable">$RETVAL</span> = 0 ] &amp;&amp; rm -f <span class="variable">$redis_pid</span> /var/lock/subsys/<span class="variable">$prog</span>  </div><div class="line"></div><div class="line">    RETVAL=$?  </div><div class="line">    <span class="built_in">return</span> <span class="variable">$RETVAL</span>  </div><div class="line">&#125;  </div><div class="line"></div><div class="line"></div><div class="line"><span class="comment"># See how we were called.  </span></div><div class="line"><span class="keyword">case</span> <span class="string">"<span class="variable">$1</span>"</span> <span class="keyword">in</span>  </div><div class="line">    start)  </div><div class="line">        start  </div><div class="line">        ;;  </div><div class="line">    stop)  </div><div class="line">        stop  </div><div class="line">        ;;  </div><div class="line">    status)  </div><div class="line">        status <span class="variable">$prog</span>  </div><div class="line">        RETVAL=$?  </div><div class="line">        ;;  </div><div class="line">    restart)  </div><div class="line">        stop  </div><div class="line">        start  </div><div class="line">        ;;  </div><div class="line">    condrestart)  </div><div class="line">        <span class="keyword">if</span> <span class="built_in">test</span> <span class="string">"x`pidof redis`"</span> != x; <span class="keyword">then</span>  </div><div class="line">            stop  </div><div class="line">            start  </div><div class="line">        <span class="keyword">fi</span>  </div><div class="line">        ;;  </div><div class="line">    *)  </div><div class="line">        <span class="built_in">echo</span> $<span class="string">"Usage: <span class="variable">$0</span> &#123;start|stop|status|restart|condrestart&#125;"</span>  </div><div class="line">        <span class="built_in">exit</span> 1  </div><div class="line"><span class="keyword">esac</span>  </div><div class="line"><span class="built_in">exit</span> <span class="variable">$RETVAL</span>  </div><div class="line">``` </div><div class="line"> </div><div class="line"><span class="comment">#### 引用</span></div><div class="line"></div><div class="line">```bash</div><div class="line"><span class="comment"># service redis-server restart</span></div><div class="line">Stopping redis                                             [失败]</div><div class="line">Starting redis                                             [确定]</div><div class="line"><span class="comment"># service redis-server status </span></div><div class="line">redis (pid  14965) 正在运行...</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;非常方便！</p>

	

	

</article>




	<article>
	
		<h1><a href="/2017/10/12/Redis/14. 为什么使用 Redis及其产品定位/">为什么使用 Redis及其产品定位</a></h1>
	
	<div class="article__infos">
		<span class="article__date">2017-10-12</span><br />
		
		
			<span class="article__tags">
			  	<a class="article__tag-link" href="/tags/Redis/">Redis</a>
			</span>
		
	</div>

	

	
		<h2 id="传统MySQL-Memcached架构遇到的问题"><a href="#传统MySQL-Memcached架构遇到的问题" class="headerlink" title="传统MySQL+ Memcached架构遇到的问题"></a>传统MySQL+ Memcached架构遇到的问题</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;实际MySQL是适合进行海量数据存储的，通过Memcached将热点数据加载到cache，加速访问，很多公司都曾经使用过这样的架构，但随着业务数据量的不断增加，和访问量的持续增长，我们遇到了很多问题：</p>
<ol>
<li>MySQL需要不断进行拆库拆表，Memcached也需不断跟着扩容，扩容和维护工作占据大量开发时间。</li>
<li>Memcached与MySQL数据库数据一致性问题。</li>
<li>Memcached数据命中率低或down机，大量访问直接穿透到DB，MySQL无法支撑。</li>
<li>跨机房cache同步问题。</li>
</ol>
<h2 id="众多NoSQL百花齐放，如何选择"><a href="#众多NoSQL百花齐放，如何选择" class="headerlink" title="众多NoSQL百花齐放，如何选择"></a>众多NoSQL百花齐放，如何选择</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;最近几年，业界不断涌现出很多各种各样的NoSQL产品，那么如何才能正确地使用好这些产品，最大化地发挥其长处，是我们需要深入研究和思考的问题，实际归根结底最重要的是了解这些产品的定位，并且了解到每款产品的tradeoffs，在实际应用中做到扬长避短，总体上这些NoSQL主要用于解决以下几种问题</p>
<ol>
<li>少量数据存储，高速读写访问。此类产品通过数据全部in-momery 的方式来保证高速访问，同时提供数据落地的功能，实际这正是Redis最主要的适用场景。</li>
<li>海量数据存储，分布式系统支持，数据一致性保证，方便的集群节点添加/删除。</li>
<li>这方面最具代表性的是dynamo和bigtable 2篇论文所阐述的思路。前者是一个完全无中心的设计，节点之间通过gossip方式传递集群信息，数据保证最终一致性，后者是一个中心化的方案设计，通过类似一个分布式锁服务来保证强一致性,数据写入先写内存和redo log，然后定期compat归并到磁盘上，将随机写优化为顺序写，提高写入性能。</li>
<li>Schema free，auto-sharding等。比如目前常见的一些文档数据库都是支持schema-free的，直接存储json格式数据，并且支持auto-sharding等功能，比如mongodb。</li>
</ol>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;面对这些不同类型的NoSQL产品,我们需要根据我们的业务场景选择最合适的产品。</p>
<h2 id="Redis适用场景，如何正确的使用"><a href="#Redis适用场景，如何正确的使用" class="headerlink" title="Redis适用场景，如何正确的使用"></a>Redis适用场景，如何正确的使用</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;前面已经分析过，Redis最适合所有数据in-momory的场景，虽然Redis也提供持久化功能，但实际更多的是一个disk-backed的功能，跟传统意义上的持久化有比较大的差别，那么可能大家就会有疑问，似乎Redis更像一个加强版的Memcached，那么何时使用Memcached,何时使用Redis呢？</p>
<h2 id="Redis与Memcached的比较"><a href="#Redis与Memcached的比较" class="headerlink" title="Redis与Memcached的比较"></a>Redis与Memcached的比较</h2><h3 id="1-网络IO模型"><a href="#1-网络IO模型" class="headerlink" title="1. 网络IO模型"></a>1. 网络IO模型</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Memcached是多线程，非阻塞IO复用的网络模型，分为监听主线程和worker子线程，监听线程监听网络连接，接受请求后，将连接描述字pipe 传递给worker线程，进行读写IO, 网络层使用libevent封装的事件库，多线程模型可以发挥多核作用，但是引入了cache coherency和锁的问题，比如，Memcached最常用的stats 命令，实际Memcached所有操作都要对这个全局变量加锁，进行计数等工作，带来了性能损耗。</p>
<p><figure class="figure"><img src="https://github.com/hcldirgit/image/blob/master/%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BD%BF%E7%94%A8%20Redis%E5%8F%8A%E5%85%B6%E4%BA%A7%E5%93%81%E5%AE%9A%E4%BD%8D/01.jpeg?raw=true" alt=""></figure></p>
<p>（Memcached网络IO模型）</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis使用单线程的IO复用模型，自己封装了一个简单的AeEvent事件处理框架，主要实现了epoll、kqueue和select，对于单纯只有IO操作来说，单线程可以将速度优势发挥到最大，但是Redis也提供了一些简单的计算功能，比如排序、聚合等，对于这些操作，单线程模型实际会严重影响整体吞吐量，CPU计算过程中，整个IO调度都是被阻塞住的。</p>
<h3 id="2-内存管理方面"><a href="#2-内存管理方面" class="headerlink" title="2. 内存管理方面"></a>2. 内存管理方面</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Memcached使用预分配的内存池的方式，使用slab和大小不同的chunk来管理内存，Item根据大小选择合适的chunk存储，内存池的方式可以省去申请/释放内存的开销，并且能减小内存碎片产生，但这种方式也会带来一定程度上的空间浪费，并且在内存仍然有很大空间时，新的数据也可能会被剔除，原因可以参考文章：<a href="https://hcldirgit.github.io/2017/08/23/Memcached/4.%20Memcached%E6%95%B0%E6%8D%AE%E8%A2%AB%E8%B8%A2(evictions0" target="_blank" rel="external">Memcached数据被踢(evictions0)现象分析</a>%E7%8E%B0%E8%B1%A1%E5%88%86%E6%9E%90/)</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis使用现场申请内存的方式来存储数据，并且很少使用free-list等方式来优化内存分配，会在一定程度上存在内存碎片，Redis跟据存储命令参数，会把带过期时间的数据单独存放在一起，并把它们称为临时数据，非临时数据是永远不会被剔除的，即便物理内存不够，导致swap也不会剔除任何非临时数据（但会尝试剔除部分临时数据），这点上Redis更适合作为存储而不是cache。</p>
<h3 id="3-数据一致性问题"><a href="#3-数据一致性问题" class="headerlink" title="3. 数据一致性问题"></a>3. 数据一致性问题</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Memcached提供了cas命令，可以保证多个并发访问操作同一份数据的一致性问题。 Redis没有提供cas 命令，并不能保证这点，不过Redis提供了事务的功能，可以保证一串 命令的原子性，中间不会被任何操作打断。</p>
<h3 id="4-存储方式及其它方面"><a href="#4-存储方式及其它方面" class="headerlink" title="4. 存储方式及其它方面"></a>4. 存储方式及其它方面</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Memcached基本只支持简单的key-value存储，不支持枚举，不支持持久化和复制等功能</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis除key/value之外，还支持list,set,sorted set,hash等众多数据结构，提供了KEYS</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;进行枚举操作，但不能在线上使用，如果需要枚举线上数据，Redis提供了工具可以直接扫描其dump文件，枚举出所有数据，Redis还同时提供了持久化和复制等功能。</p>
<h3 id="5-关于不同语言的客户端支持"><a href="#5-关于不同语言的客户端支持" class="headerlink" title="5. 关于不同语言的客户端支持"></a>5. 关于不同语言的客户端支持</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在不同语言的客户端方面，Memcached和Redis都有丰富的第三方客户端可供选择，不过因为Memcached发展的时间更久一些，目前看在客户端支持方面，Memcached的很多客户端更加成熟稳定，而Redis由于其协议本身就比Memcached复杂，加上作者不断增加新的功能等，对应第三方客户端跟进速度可能会赶不上，有时可能需要自己在第三方客户端基础上做些修改才能更好的使用。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;根据以上比较不难看出，当我们不希望数据被踢出，或者需要除key/value之外的更多数据类型时，或者需要落地功能时，使用Redis比使用Memcached更合适。</p>
<h2 id="关于Redis的一些周边功能"><a href="#关于Redis的一些周边功能" class="headerlink" title="关于Redis的一些周边功能"></a>关于Redis的一些周边功能</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis除了作为存储之外还提供了一些其它方面的功能，比如聚合计算、pubsub、scripting等，对于此类功能需要了解其实现原理，清楚地了解到它的局限性后，才能正确的使用，比如pubsub功能，这个实际是没有任何持久化支持的，消费方连接闪断或重连之间过来的消息是会全部丢失的，又比如聚合计算和scripting等功能受Redis单线程模型所限，是不可能达到很高的吞吐量的，需要谨慎使用。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;总的来说Redis作者是一位非常勤奋的开发者，可以经常看到作者在尝试着各种不同的新鲜想法和思路，针对这些方面的功能就要求我们需要深入了解后再使用。</p>
<h2 id="总结："><a href="#总结：" class="headerlink" title="总结："></a>总结：</h2><ol>
<li>Redis使用最佳方式是全部数据in-memory。</li>
<li>Redis更多场景是作为Memcached的替代者来使用。</li>
<li>当需要除key/value之外的更多数据类型支持时，使用Redis更合适。</li>
<li>当存储的数据不能被剔除时，使用Redis更合适。</li>
</ol>

	

	

</article>




	<article>
	
		<h1><a href="/2017/10/12/Redis/13. 十五分钟介绍 Redis数据结构/">十五分钟介绍 Redis数据结构</a></h1>
	
	<div class="article__infos">
		<span class="article__date">2017-10-12</span><br />
		
		
			<span class="article__tags">
			  	<a class="article__tag-link" href="/tags/Redis/">Redis</a>
			</span>
		
	</div>

	

	
		<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;下面是一个对Redis官方文档<a href="https://redis.io/topics/data-types-intro" target="_blank" rel="external">《A fifteen minute introduction to Redis data types》</a>一文的翻译，如其题目所言，此文目的在于让一个初学者能通过15分钟的简单学习对Redis的数据结构有一个了解。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis是一种面向“键/值”对类型数据的分布式NoSQL数据库系统，特点是高性能，持久存储，适应高并发的应用场景。它起步较晚，发展迅速，目前已被许多大型机构采用，比如Github，看看谁在用它。</p>
<hr>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;你也许已经知道Redis并不是简单的key-value存储，实际上他是一个数据结构服务器，支持不同类型的值。也就是说，你不必仅仅把字符串当作键所指向的值。下列这些数据类型都可作为值类型。</p>
<ul>
<li>二进制安全的 字符串 string</li>
<li>二进制安全的 字符串列表 list of string</li>
<li>二进制安全的 字符串集合 set of string，换言之：它是一组无重复未排序的element。可以把它看成Ruby中的 hash–其key等于element，value都等于’true‘。</li>
<li>有序集合sorted set of string，类似于集合set，但其中每个元素都和一个浮点数score（评分）关联。element根据score排序。可以把它看成Ruby中的 hash–其key等于element，value等于score，但元素总是按score的顺序排列，无需额外的排序操作。</li>
</ul>
<h2 id="Redis-键"><a href="#Redis-键" class="headerlink" title="Redis 键"></a>Redis 键</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis key值是二进制安全的，这意味着可以用任何二进制序列作为key值，从形如”foo”的简单字符串到一个JPEG文件的内容都可以。空字符串也是有效key值。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;关于key的几条规则：</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;太长的键值不是个好主意，例如1024字节的键值就不是个好主意，不仅因为消耗内存，而且在数据中查找这类键值的计算成本很高。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;太短的键值通常也不是好主意，如果你要用”u:1000:pwd”来代替”user:1000:password”，这没有什么问题，但后者更易阅读，并且由此增加的空间消耗相对于key object和value object本身来说很小。当然，没人阻止您一定要用更短的键值节省一丁点儿空间。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;最好坚持一种模式。例如：”object-type:id:field”就是个不错的注意，像这样”user:1000:password”。我喜欢对多单词的字段名中加上一个点，就像这样：”comment:1234:reply.to”。</p>
<h2 id="字符串类型"><a href="#字符串类型" class="headerlink" title="字符串类型"></a>字符串类型</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;这是最简单Redis类型。如果你只用这种类型，Redis就像一个可以持久化的memcached服务器（注：memcache的数据仅保存在内存中，服务器重启后，数据将丢失）。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;我们来玩儿一下字符串类型：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">$ redis-cli <span class="built_in">set</span> mykey <span class="string">"my binary safe value"</span></div><div class="line">OK</div><div class="line">$ redis-cli get mykey</div><div class="line">my binary safe value</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;正如你所见到的，通常用SET command 和 GET command来设置和获取字符串值。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;值可以是任何种类的字符串（包括二进制数据），例如你可以在一个键下保存一副jpeg图片。值的长度不能超过1GB。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;虽然字符串是Redis的基本值类型，但你仍然能通过它完成一些有趣的操作。例如：原子递增：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">$ redis-cli <span class="built_in">set</span> counter 100</div><div class="line">OK $ redis-cli incr counter</div><div class="line">(<span class="built_in">integer</span>) 101</div><div class="line">$ redis-cli incr counter</div><div class="line">(<span class="built_in">integer</span>) 102</div><div class="line">$ redis-cli incrby counter 10</div><div class="line">(<span class="built_in">integer</span>) 112</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;INCR 命令将字符串值解析成整型，将其加一，最后将结果保存为新的字符串值，类似的命令有INCRBY, DECR and DECRBY。实际上他们在内部就是同一个命令，只是看上去有点儿不同。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;INCR是原子操作意味着什么呢？就是说即使多个客户端对同一个key发出INCR命令，也决不会导致竞争的情况。例如如下情况永远不可能发生：『客户端1和客户端2同时读出“10”，他们俩都对其加到11，然后将新值设置为11』。最终的值一定是12，read-increment-set操作完成时，其他客户端不会在同一时间执行任何命令。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;对字符串，另一个的令人感兴趣的操作是GETSET命令，行如其名：他为key设置新值并且返回原值。这有什么用处呢？例如：你的系统每当有新用户访问时就用INCR命令操作一个Redis key。你希望每小时对这个信息收集一次。你就可以GETSET这个key并给其赋值0并读取原值。</p>
<h2 id="列表类型"><a href="#列表类型" class="headerlink" title="列表类型"></a>列表类型</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;要说清楚列表数据类型，最好先讲一点儿理论背景，在信息技术界List这个词常常被使用不当。例如”Python Lists”就名不副实（名为Linked Lists），但他们实际上是数组（同样的数据类型在Ruby中叫数组）</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;一般意义上讲，列表就是有序元素的序列：10,20,1,2,3就是一个列表。但用数组实现的List和用Linked List实现的List，在属性方面大不相同。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis lists基于Linked Lists实现。这意味着即使在一个list中有数百万个元素，在头部或尾部添加一个元素的操作，其时间复杂度也是常数级别的。用LPUSH 命令在十个元素的list头部添加新元素，和在千万元素list头部添加新元素的速度相同。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;那么，坏消息是什么？在数组实现的list中利用索引访问元素的速度极快，而同样的操作在linked list实现的list上没有那么快。</p>
<blockquote>
<p>Redis Lists are implemented with linked lists because for a database system it is crucial to be able to add elements to a very long list in a very fast way. Another strong advantage is, as you’ll see in a moment, that Redis Lists can be taken at constant length in constant time.</p>
</blockquote>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis Lists用linked list实现的原因是：对于数据库系统来说，至关重要的特性是：能非常快的在很大的列表上添加元素。另一个重要因素是，正如你将要看到的：Redis lists能在常数时间取得常数长度。</p>
<h2 id="Redis-lists-入门"><a href="#Redis-lists-入门" class="headerlink" title="Redis lists 入门"></a>Redis lists 入门</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;LPUSH 命令可向list的左边（头部）添加一个新元素，而RPUSH命令可向list的右边（尾部）添加一个新元素。最后LRANGE 命令可从list中取出一定范围的元素</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line">$ redis-cli rpush messages <span class="string">"Hello how are you?"</span></div><div class="line">OK</div><div class="line">$ redis-cli rpush messages <span class="string">"Fine thanks. I‘m having fun with Redis"</span></div><div class="line">OK</div><div class="line">$ redis-cli rpush messages <span class="string">"I should look into this NOSQL thing ASAP"</span></div><div class="line">OK</div><div class="line">$ redis-cli lrange messages 0 2</div><div class="line">1. Hello how are you?</div><div class="line">2. Fine thanks. I‘m having fun with Redis</div><div class="line">3. I should look into this NOSQL thing ASAP</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;注意LRANGE 带有两个索引，一定范围的第一个和最后一个元素。这两个索引都可以为负来告知Redis从尾部开始计数，因此-1表示最后一个元素，-2表示list中的倒数第二个元素，以此类推。</p>
<blockquote>
<p>As you can guess from the example above, lists can be used, for instance, in order to implement a chat system. Another use is as queues in order to route messages between different processes. But the key point is that you can use Redis lists every time you require to access data in the same order they are added. This will not require any SQL ORDER BY operation, will be very fast, and will scale to millions of elements even with a toy Linux box.</p>
</blockquote>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;正如你可以从上面的例子中猜到的，list可被用来实现聊天系统。还可以作为不同进程间传递消息的队列。关键是，你可以每次都以原先添加的顺序访问数据。这不需要任何SQL ORDER BY 操作，将会非常快，也会很容易扩展到百万级别元素的规模。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;例如在评级系统中，比如社会化新闻网站 reddit.com，你可以把每个新提交的链接添加到一个list，用LRANGE可简单的对结果分页。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在博客引擎实现中，你可为每篇日志设置一个list，在该list中推入进博客评论，等等。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;向Redis list压入ID而不是实际的数据</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在上面的例子里 ，我们将“对象”（此例中是简单消息）直接压入Redis list，但通常不应这么做，由于对象可能被多次引用：例如在一个list中维护其时间顺序，在一个集合中保存它的类别，只要有必要，它还会出现在其他list中，等等。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;让我们回到reddit.com的例子，将用户提交的链接（新闻）添加到list中，有更可靠的方法如下所示：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">$ redis-cli incr next.news.id</div><div class="line">(<span class="built_in">integer</span>) 1</div><div class="line">$ redis-cli <span class="built_in">set</span> news:1:title <span class="string">"Redis is simple"</span></div><div class="line">OK</div><div class="line">$ redis-cli <span class="built_in">set</span> news:1:url <span class="string">"http://code.google.com/p/redis"</span></div><div class="line">OK</div><div class="line">$ redis-cli lpush submitted.news 1</div><div class="line">OK</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;我们自增一个key，很容易得到一个独一无二的自增ID，然后通过此ID创建对象–为对象的每个字段设置一个key。最后将新对象的ID压入submitted.news list。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;这只是牛刀小试。在命令参考文档中可以读到所有和list有关的命令。你可以删除元素，旋转list，根据索引获取和设置元素，当然也可以用LLEN得到list的长度。</p>
<h2 id="Redis-集合"><a href="#Redis-集合" class="headerlink" title="Redis 集合"></a>Redis 集合</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis集合是未排序的集合，其元素是二进制安全的字符串。SADD命令可以向集合添加一个新元素。和sets相关的操作也有许多，比如检测某个元素是否存在，以及实现交集，并集，差集等等。一例胜千言：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line">$ redis-cli sadd myset 1</div><div class="line">(<span class="built_in">integer</span>) 1</div><div class="line">$ redis-cli sadd myset 2</div><div class="line">(<span class="built_in">integer</span>) 1</div><div class="line">$ redis-cli sadd myset 3</div><div class="line">(<span class="built_in">integer</span>) 1</div><div class="line">$ redis-cli smembers myset</div><div class="line">1. 3</div><div class="line">2. 1</div><div class="line">3. 2</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;我向集合中添加了三个元素，并让Redis返回所有元素。如你所见它们是无序的。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;现在让我们检查某个元素是否存在：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">$ redis-cli sismember myset 3</div><div class="line">(<span class="built_in">integer</span>) 1</div><div class="line">$ redis-cli sismember myset 30</div><div class="line">(<span class="built_in">integer</span>) 0</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;“3″是这个集合的成员，而“30”不是。集合特别适合表现对象之间的关系。例如用Redis集合可以很容易实现标签功能。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;下面是一个简单的方案：对每个想加标签的对象，用一个标签ID集合与之关联，并且对每个已有的标签，一组对象ID与之关联。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;例如假设我们的新闻ID 1000被加了三个标签tag 1,2,5和77，就可以设置下面两个集合：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line">$ redis-cli sadd news:1000:tags 1</div><div class="line">(<span class="built_in">integer</span>) 1</div><div class="line">$ redis-cli sadd news:1000:tags 2</div><div class="line">(<span class="built_in">integer</span>) 1</div><div class="line">$ redis-cli sadd news:1000:tags 5</div><div class="line">(<span class="built_in">integer</span>) 1</div><div class="line">$ redis-cli sadd news:1000:tags 77</div><div class="line">(<span class="built_in">integer</span>) 1</div><div class="line">$ redis-cli sadd tag:1:objects 1000</div><div class="line">(<span class="built_in">integer</span>) 1</div><div class="line">$ redis-cli sadd tag:2:objects 1000</div><div class="line">(<span class="built_in">integer</span>) 1</div><div class="line">$ redis-cli sadd tag:5:objects 1000</div><div class="line">(<span class="built_in">integer</span>) 1</div><div class="line">$ redis-cli sadd tag:77:objects 1000</div><div class="line">(<span class="built_in">integer</span>) 1</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;要获取一个对象的所有标签，如此简单：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">$ redis-cli smembers news:1000:tags</div><div class="line">1. 5</div><div class="line">2. 1</div><div class="line">3. 77</div><div class="line">4. 2</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;而有些看上去并不简单的操作仍然能使用相应的Redis命令轻松实现。例如我们也许想获得一份同时拥有标签1, 2, 10和27的对象列表。这可以用SINTER命令来做，他可以在不同集合之间取出交集。因此为达目的我们只需：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">$ redis-cli sinter tag:1:objects tag:2:objects tag:10:objects tag:27:objects</div><div class="line">... no result <span class="keyword">in</span> our dataset composed of just one object </div><div class="line"> </div><div class="line"> ...</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在命令参考文档中可以找到和集合相关的其他命令，令人感兴趣的一抓一大把。一定要留意SORT命令，Redis集合和list都是可排序的。</p>
<h2 id="题外话：如何为字符串获取唯一标识"><a href="#题外话：如何为字符串获取唯一标识" class="headerlink" title="题外话：如何为字符串获取唯一标识"></a>题外话：如何为字符串获取唯一标识</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在标签的例子里，我们用到了标签ID，却没有提到ID从何而来。基本上你得为每个加入系统的标签分配一个唯一标识。你也希望在多个客户端同时试着添加同样的标签时不要出现竞争的情况。此外，如果标签已存在，你希望返回他的ID，否则创建一个新的唯一标识并将其与此标签关联。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis 1.4将增加Hash类型。有了它，字符串和唯一ID关联的事儿将不值一提，但如今我们如何用现有Redis命令可靠的解决它呢？</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;我们首先的尝试（以失败告终）可能如下。假设我们想为标签“redis”获取一个唯一ID：</p>
<ul>
<li>为了让算法是二进制安全的（只是标签而不考虑utf8，空格等等）我们对标签做SHA1签名。SHA1(redis)=b840fc02d524045429941cc15f59e41cb7be6c52。</li>
<li>检查这个标签是否已与一个唯一ID关联，</li>
<li>用命令GET tag:b840fc02d524045429941cc15f59e41cb7be6c52:id</li>
<li>如果上面的GET操作返回一个ID，则将其返回给用户。标签已经存在了。</li>
<li>否则… 用INCR next.tag.id命令生成一个新的唯一ID（假定它返回123456）。</li>
<li>最后关联标签和新的ID，</li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">SET tag:b840fc02d524045429941cc15f59e41cb7be6c52:id 123456</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;并将新ID返回给调用者。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;多美妙，或许更好…等等！当两个客户端同时使用这组指令尝试为标签“redis”获取唯一ID时会发生什么呢？如果时间凑巧，他们俩都会从GET操作获得nil，都将对next.tag.id key做自增操作，这个key会被自增两次。其中一个客户端会将错误的ID返回给调用者。幸运的是修复这个算法并不难，这是明智的版本：</p>
<ul>
<li>为了让算法是二进制安全的（只是标签而不考虑utf8，空格等等）我们对标签做SHA1签名。SHA1(redis)=b840fc02d524045429941cc15f59e41cb7be6c52。</li>
<li>检查这个标签是否已与一个唯一ID关联，</li>
<li>用命令GET tag:b840fc02d524045429941cc15f59e41cb7be6c52:id<br>如果上面的GET操作返回一个ID，则将其返回给用户。标签已经存在了。</li>
<li>否则… 用INCR next.tag.id命令生成一个新的唯一ID（假定它返回123456）。</li>
<li>下面关联标签和新的ID，(注意用到一个新的命令)</li>
</ul>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;SETNX tag:b840fc02d524045429941cc15f59e41cb7be6c52:id 123456。。如果另一个客户端比当前客户端更快，SETNX将不会设置key。而且，当key被成功设置时SETNX返回1，否则返回0。那么…让我们再做最后一步运算。</p>
<ul>
<li>如果SETNX返回1（key设置成功）则将123456返回给调用者，这就是我们的标签ID，否则执行GET tag:b840fc02d524045429941cc15f59e41cb7be6c52:id 并将其结果返回给调用者。</li>
</ul>
<h2 id="有序集合"><a href="#有序集合" class="headerlink" title="有序集合"></a>有序集合</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;集合是使用频率很高的数据类型，但是…对许多问题来说他们也有点儿太不讲顺序了;)因此Redis1.2引入了有序集合。他和集合非常相似，也是二进制安全的字符串集合，但是这次带有关联的score，以及一个类似LRANGE的操作可以返回有序元素，此操作只能作用于有序集合，它就是，ZRANGE 命令。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;基本上有序集合从某种程度上说是SQL世界的索引在Redis中的等价物。例如在上面提到的reddit.com例子中，并没有提到如何根据用户投票和时间因素将新闻组合生成首页。我们将看到有序集合如何解决这个问题，但最好先从更简单的事情开始，阐明这个高级数据类型是如何工作的。让我们添加几个黑客，并将他们的生日作为“score”。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">$ redis-cli zadd hackers 1940 <span class="string">"Alan Kay"</span></div><div class="line">(<span class="built_in">integer</span>) 1</div><div class="line">$ redis-cli zadd hackers 1953 <span class="string">"Richard Stallman"</span></div><div class="line">(<span class="built_in">integer</span>) 1</div><div class="line">$ redis-cli zadd hackers 1965 <span class="string">"Yukihiro Matsumoto"</span></div><div class="line">(<span class="built_in">integer</span>) 1</div><div class="line">$ redis-cli zadd hackers 1916 <span class="string">"Claude Shannon"</span></div><div class="line">(<span class="built_in">integer</span>) 1</div><div class="line">$ redis-cli zadd hackers 1969 <span class="string">"Linus Torvalds"</span></div><div class="line">(<span class="built_in">integer</span>) 1</div><div class="line">$ redis-cli zadd hackers 1912 <span class="string">"Alan Turing"</span></div><div class="line">(<span class="built_in">integer</span>) 1</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;对有序集合来说，按生日排序返回这些黑客易如反掌，因为他们已经是有序的。有序集合是通过一个dual-ported 数据结构实现的，它包含一个精简的有序列表和一个hash table，因此添加一个元素的时间复杂度是O(log(N))。这还行，但当我们需要访问有序的元素时，Redis不必再做任何事情，它已经是有序的了：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">$ redis-cli zrange hackers 0 -1</div><div class="line">1. Alan Turing</div><div class="line">2. Claude Shannon</div><div class="line">3. Alan Kay</div><div class="line">4. Richard Stallman</div><div class="line">5. Yukihiro Matsumoto</div><div class="line">6. Linus Torvalds</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;你知道Linus比Yukihiro年轻吗<br>无论如何，我想反向对这些元素排序，这次就用 ZREVRANGE 代替 ZRANGE 吧：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">$ redis-cli zrevrange hackers 0 -1</div><div class="line">1. Linus Torvalds</div><div class="line">2. Yukihiro Matsumoto</div><div class="line">3. Richard Stallman</div><div class="line">4. Alan Kay</div><div class="line">5. Claude Shannon</div><div class="line">6. Alan Turing</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;一个非常重要的小贴士，ZSets只是有一个“默认的”顺序，但你仍然可以用 SORT 命令对有序集合做不同的排序（但这次服务器要耗费CPU了）。要想得到多种排序，一种可选方案是同时将每个元素加入多个有序集合。</p>
<h2 id="区间操作"><a href="#区间操作" class="headerlink" title="区间操作"></a>区间操作</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;有序集合之能不止于此，他能在区间上操作。例如获取所有1950年之前出生的人。我们用 ZRANGEBYSCORE 命令来做：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">$ redis-cli zrangebyscore hackers -inf 1950</div><div class="line">1. Alan Turing</div><div class="line">2. Claude Shannon</div><div class="line">3. Alan Kay</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;我们请求Redis返回score介于负无穷到1950年之间的元素（两个极值也包含了）。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;也可以删除区间内的元素。例如从有序集合中删除生日介于1940到1960年之间的黑客。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">$ redis-cli zremrangebyscore hackers 1940 1960</div><div class="line">(<span class="built_in">integer</span>) 2</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;ZREMRANGEBYSCORE 这个名字虽然不算好，但他却非常有用，还会返回已删除的元素数量。</p>
<h2 id="回到Reddit的例子"><a href="#回到Reddit的例子" class="headerlink" title="回到Reddit的例子"></a>回到Reddit的例子</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;最后，回到 Reddit的例子。现在我们有个基于有序集合的像样方案来生成首页。用一个有序集合来包含最近几天的新闻（用 ZREMRANGEBYSCORE 不时的删除旧新闻）。用一个后台任务从有序集合中获取所有元素，根据用户投票和新闻时间计算score，然后用新闻IDs和scores关联生成 reddit.home.page 有序集合。要显示首页，我们只需闪电般的调用 ZRANGE。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;不时的从 reddit.home.page 有序集合中删除过旧的新闻也是为了让我们的系统总是工作在有限的新闻集合之上。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;更新有序集合的scores</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;结束这篇指南之前还有最后一个小贴士。有序集合scores可以在任何时候更新。只要用 ZADD 对有序集合内的元素操作就会更新它的score（和位置），时间复杂度是O(log(N))，因此即使大量更新，有序集合也是合适的。</p>

	

	

</article>




	<article>
	
		<h1><a href="/2017/10/12/Redis/11. Redis内存使用优化与存储/">Redis内存使用优化与存储</a></h1>
	
	<div class="article__infos">
		<span class="article__date">2017-10-12</span><br />
		
		
			<span class="article__tags">
			  	<a class="article__tag-link" href="/tags/Redis/">Redis</a>
			</span>
		
	</div>

	

	
		<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis常见数据模型的使用场景以及在内存优化方面和性能优化方面的分析：</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;常见类型：String、 Hash、 set、 sorted set、 list  五种。。。。。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;五种数据类型是在内存管理中的描述：</p>
<p> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;首先Redis内部使用一个redisObject对象来表示所有的key和value，如下图所讲，type代表一个value对象具体是何种数据类型，encoding</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;是不同数据类型在redis内部的存储方式，比如，type=string代表value存储的是一个普通字符串，那么对应的encoding可以是raw或int，如果是int则代表实际redis内部是按数值类型存储和表示这个type的string。。当然这个字符串本是可以用数值表示。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;vm字段：redis的虚拟内存功能只有打开了，此字段才会真正的分配内存，该功能默认是关闭的。</p>
<p><figure class="figure"><img src="https://github.com/hcldirgit/image/blob/master/Redis%E5%86%85%E5%AD%98%E4%BD%BF%E7%94%A8%E4%BC%98%E5%8C%96%E4%B8%8E%E5%AD%98%E5%82%A8/01.jpeg?raw=true" alt=""></figure></p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;分析五中数据类型的使用和内部实现方式：</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;String ：常用命令：set– get—decr—incr—mget–等</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;应用场景：String是最常用的一种数据类型，普通的key’value存储都可以归为此类，</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;实现方式：String在redis内部默认是就是一个字符串，被redisObject所引用，当遇到incr，decr等操作时，会转成数值型进行计算。此时的redisObject的encoding字段为int。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Hash ：常用命令—-hget，hset，hgetall等</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;应用场景：用存储一个用户信息对象数据为例：</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;用户ID为查找的key，存储value用户对象包含姓名，年龄，生日等信息。如果用普通的key，value结构来存储，主要是下面两种存储方式：</p>
<p><figure class="figure"><img src="https://github.com/hcldirgit/image/blob/master/Redis%E5%86%85%E5%AD%98%E4%BD%BF%E7%94%A8%E4%BC%98%E5%8C%96%E4%B8%8E%E5%AD%98%E5%82%A8/02.jpeg?raw=true" alt=""></figure></p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;这种方式将用户ID作为查找key，把其他信息封装成一个对象，以序列化的方式存储，这种方式的缺点，增加了序列化\反序列化的开销，并且在需要修改其中一项信息时，需要把整个对象取回，并且修改操作需要对并发进行保护，引入CAS等复杂问题。</p>
<p><figure class="figure"><img src="https://github.com/hcldirgit/image/blob/master/Redis%E5%86%85%E5%AD%98%E4%BD%BF%E7%94%A8%E4%BC%98%E5%8C%96%E4%B8%8E%E5%AD%98%E5%82%A8/03.jpeg?raw=true" alt=""></figure></p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;上面的第二种方法是这个用户信息对象有多少成员就存成多少个key-value对儿。用用户ID+对应属性的名称作为以为标识来取得属性的值。但这样造成了ID重复存取。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;这样的话，使用Hash结构就可以更好的处理了：</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis的hash实际是内部存储的value为一个hashmap，并踢狗了直接存取这个Map成员的接口，如下图：</p>
<p><figure class="figure"><img src="https://github.com/hcldirgit/image/blob/master/Redis%E5%86%85%E5%AD%98%E4%BD%BF%E7%94%A8%E4%BC%98%E5%8C%96%E4%B8%8E%E5%AD%98%E5%82%A8/04.jpeg?raw=true" alt=""></figure></p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;这样key仍然是用户ID，value是一个Map，这个Map的key是成员的属性名，value是属性值。这样 对数据的修改和存取都可以直接通过内部Map的key（Redis里称内部map的key为field）。也就是通过key（用户id）+field（属性标签）就可以操作对应的属性数据了。既不需要重复存储数据，也不会带来序列化和并发修改控制的问题。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;但这里需注意的是hgetall命令，这个接口命令可以取到全部的属性数据，但是如果内部Map的成员很多，那么涉及到遍历整个内部Map的操作，由于Redis单线程模型的缘故，这个遍历操作可能会比较耗时。。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;实现方式：</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;上面提到Redis的hash对应的内部value内部实际就是一个HashMap，而实际这里会有两种不同实现，这个hash的成员比较少时，Redis为了节省内存会采用类似一维数组的方式来紧凑存储，而不是真正的hashMap结构，对应的value redisObject 的encoding为zipmap，当成员数量增大时会自动转成真正的HashMap。此时encoding为ht。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;List  ：常用命令：lpush，rpush，lpop，rpop，lrange等。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;应用场景：Redis list应用场景非常多，也是redis 的重要的数据结构之一。比如twitter的关注列表，粉丝列表都可以用redis的list结构来实现。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;实现方式：redis的list实际是一个双向链表 —— 即可以支持 反向查找和遍历，更方面操作，不过带来了部分额外的内存开销，redis内部很多实现包括发送缓冲队列等也都是用这个数据结构。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Set ：常用命令：sadd 、 spop、smembers，sunion等</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;应用场景：对外提供的功能与list类似是一个列表的功能。特殊之处，在于set是可以自动排重的，当你需要存储一个列表数据，又不希望出现重复数据时，set是一个很好的选择，并且set提供了判断某个成员是否在一个set集合内的重要接口，这个也是list所不能提供的。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;实现方式：set 的内部实现是一个value 永远为nullHashMap，实际就是通过计算hash的方式来快速排重的，这也是set能提供判断一个成员是否在集合内的原因。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Sorted set ：常用命令：zadd、zrange、zrem、zcard等。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;使用场景：使用与set类似。区别是set不是自动有序的。而sorted set可以通过用户额外提供一个优先级score 的参数来为成员排序，并且插入是有序的。即自动排序。当你需要一个有序的并且不重复的集合列表，那么可以选择sorted set数据结构。比如twitter的public timeline可以以发表时间作为score来存储，这样获取时就是自动按时间排序的。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;实现方式：redis sorted set的内部霍思燕那个hashMap和跳跃表（SkipList）来保证数据的存储和有序，hashMap里放的是成员到score的映射，而跳跃表里存放的是所有的成员，排序依据的是hashMap里存放的score，使用跳跃表的结构可以获得比较高的查找效率，并且在实现上比较简单。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;常用内存优化手段与参数：<br> 通过上面的实现上的分析，可以看出redis的内存管理成本比较高，即占用了过多的内存，redis的作者对这点也很清楚，所以提供了一系列的参数和手段来控制和节省内存：</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;首先最重要的一点是不要开启redis的vm选项，即虚拟内存功能。这个本来是作为redis存储超出物理内存数据的一种数据在内存与磁盘换入换出的一个持久化策略，但是其内存管理成本也很搞，并且我们后续会分析此种持久化策略并不成熟，所以关闭vm功能，所以请设置redis.conf文件中 的vm-enabled 为no。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;其次，最好设置下redis.conf中的maxmemory选项，该选项告诉redis当使用了多少物理内存后就开始拒绝后续的写入请求，该参数能很好的保护好你的redis不会因为使用过多的物理内存而导致swap，最红严重影响性能甚至崩溃。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;另外redis为不同数据类型分别提供了一组参数来控制内存使用，我们前面详细分析过redis hash是value内部为一个hashmap，如果该map 的成员比较少，则会采用类似一维线性的紧凑格式来存储该map，即省去了大量指针的内存开销，这个从拿书控制对应在redis.conf配置文件中下面两项：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">hash</span>-max-zipmap-entries 64</div><div class="line"><span class="built_in">hash</span>-max-zipmap-value 512</div><div class="line"><span class="built_in">hash</span>-max-zipmap-entres</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;含义是当value这个map内部不超过多少成员时会采用线性紧凑格式存储，默认是64，即 alue内部有64个以下的成员就是使用线性紧凑存储，超过该值就自动转成真正的hashMap。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;hash-max-zipmap-value 含义是当alue 这个map内部的每个成员值长度不超过多少字节就会采用线性紧凑存储来节省空间。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;以上两个条件，任意一条超过设置就会转成真正的hashmap，也就不会再节省内存了，那么这个值是不是设置的越大越好呢。答案当然是否定的，hashmap的优势就是查找和操作的时间复杂度都是o(1)的，而放弃hash采用一维存储则是o(n)的时间复杂度，如果成员数量很少，则影响不大，否则严重影响性能，所以要权衡这个值的设置。总体上是最根本的时间成本和空间成本上的权衡。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;同类参数还有：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">list-max-ziplist-entries 512</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;说明：list数据类型多少节点以下会采用去指针的紧凑存储格式。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">list-max-ziplist-value 64</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;说明：list数据类型节点值大小系哦啊与多少字节会采用紧凑存储格式。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">set</span>-max-inset-entries 512</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;说明set数据类型内部数据如果全部是数值型，且包含多少字节点以下，会采用紧凑存储格式。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;redis内部实现没有对内存分配方面做过多的优化，一定程度上回存在内存碎片，不过大多数的情况下，这个不会成为redis的性能瓶颈。不过如果在redis内部存储的大部分是数值型的话，redis内部采用了一个shared integer的方式来省去分配内存的开销，即在系统启动是先分配一个从1~n那么多个数值对象放在一个池子中，如果存储的数据恰好是这个数值范围内的数据，则直接诶从池子里取出对象。并且通过引用技术的方式来分享。这样在系统存储了大量数值下，也能在一定程度上节省内存并且提高ixngneng，这个参数值n的设置需要修改源代码中的一行宏定义：REDIS_SHARED_INTERGERS，该值默认为10000，可以根据自己的需要进行修改，修改后重新编译就可以了。</p>
<h2 id="redis的持久化机制"><a href="#redis的持久化机制" class="headerlink" title="redis的持久化机制:"></a>redis的持久化机制:</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;四种持久化方式：</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;定时快照方式—snapshot———-定时器事件—固定时间点检查当前数据发生的改变次数与时间是否满足触发持久化的条件。满         足时，就通过fork调用来创建一个子进程。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;这个子进程默认会与父进程共享相同的地址空间，这时就可以通过子进程来遍历整个内存来进行存储操作，而主进程则仍然可     以提供服务，当有写入时由操作系统按照内存页(page)为单位来进行copy-on-write保证父子进程之间不会互相影响。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;该持久化的主要<code>缺点是定时快照只是代表一段时间内的内存映像，所以系统重启会丢失上次快照与重启之间所有的数据</code></p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;基于语句追加文件的方式——aof——-类似mysql基于语句的binlog方式，即每条会使redis内存数据发生改变的命令都会追加到      一个log文件中，也就是说这个log文件就是redis的持久化数据。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;缺点是：追加log文件可能导致体积过大，当系统重启恢复数据时如果是aof的方式则加载数据会非常缓慢</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;虚拟内存—-vm——–已被遗弃。。。。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Diskstore方式——-B-tree</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;设计思路上，前两种基于全部数据都在内存中，即小数据量下提供磁盘落地功能。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;后两种方式则是作者在尝试存储数据超过物理内存时，即大数据量的数据存储。仍在实验阶段</p>
<h2 id="redis持久化磁盘IO方式及其带来的问题。"><a href="#redis持久化磁盘IO方式及其带来的问题。" class="headerlink" title="redis持久化磁盘IO方式及其带来的问题。"></a>redis持久化磁盘IO方式及其带来的问题。</h2><h3 id="redis-崩溃的一个原因："><a href="#redis-崩溃的一个原因：" class="headerlink" title="redis 崩溃的一个原因："></a>redis 崩溃的一个原因：</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;redis的持久化使用了buffer IO造成的，所谓buffer IO指redis对持久化文件的写入和读取操作都会使用物理内存page cache 而大多数数据库系统会使用direct IO来绕过这层page cache 并自行维护一个数据cache，。而当redis的持久化文件过大,尤其是快照文件。并对其读写时，磁盘文件中数据都会被加载到物理内存中作为操作系统对该文件的一层的cache。而这层cache的数据与redis内存中管理的数据实际是重复存储的，虽然内核在物理内存紧张时会做page cache 的剔除工作，<strong>但内核很可能会认为某个page cache 会更重要，而让你的进程开始swap，这时你的系统就会开始出现不稳定或者崩溃了</strong>。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<strong>补充</strong>：page cache，又称pcache，其中文名称为<code>页高速缓冲存储器，简称页高缓</code>。page cache的大小为一页，通常为4K。在linux读    写文件时，它用于缓存文件的逻辑内容，从而加快对磁盘上映像和数据的访问。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<strong>经验：当你的redis物理内存使用超过内存总容量的3/5，就会开始比较危险了</strong></p>
<p><figure class="figure"><img src="https://github.com/hcldirgit/image/blob/master/Redis%E5%86%85%E5%AD%98%E4%BD%BF%E7%94%A8%E4%BC%98%E5%8C%96%E4%B8%8E%E5%AD%98%E5%82%A8/05.jpeg?raw=true" alt=""></figure></p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;总结：</p>
<ol>
<li><p>根据业务需要选择核实的数据类型，并为不同的应用场景设置相应的紧凑存储参数</p>
</li>
<li><p>当业务场景不需要数据持久化时，关闭所有的持久化方式可以获得最佳的性能以及做大的内存使用量。</p>
</li>
<li><p>如果需要持久化，根据是否可以容忍重启丢失部分数据在快照方式与语句追加方式之间选择其一，不要使用虚拟内存以及diskstore方式</p>
</li>
<li><p>不要让你的redis所在机器物理内存使用超过实际内存总量的3/5。。</p>
</li>
</ol>

	

	

</article>




	<article>
	
		<h1><a href="/2017/10/12/Redis/12. 几点建议，让Redis在你的系统中发挥更大作用/">几点建议，让Redis在你的系统中发挥更大作用</a></h1>
	
	<div class="article__infos">
		<span class="article__date">2017-10-12</span><br />
		
		
			<span class="article__tags">
			  	<a class="article__tag-link" href="/tags/Redis/">Redis</a>
			</span>
		
	</div>

	

	
		<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis在很多方面与其他数据库解决方案不同：它使用内存提供主存储支持，而仅使用硬盘做持久性的存储；它的数据模型非常独特，用的是单线程。另一个大区别在于，你可以在开发环境中使用Redis的功能，但却不需要转到Redis。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;转向Redis当然也是可取的，许多开发者从一开始就把Redis作为首选数据库；但设想如果你的开发环境已经搭建好，应用已经在上面运行了，那么更换数据库框架显然不那么容易。另外在一些需要大容量数据集的应用，Redis也并不适合，因为它的数据集不会超过系统可用的内存。所以如果你有大数据应用，而且主要是读取访问模式，那么Redis并不是正确的选择。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;然而我喜欢Redis的一点就是你可以把它融入到你的系统中来，这就能够解决很多问题，比如那些你现有的数据库处理起来感到缓慢的任务。这些你就可以通过Redis来进行优化，或者为应用创建些新的功能。在本文中，我就想探讨一些怎样将Redis加入到现有的环境中，并利用它的原语命令等功能来解决传统环境中碰到的一些常见问题。在这些例子中，Redis都不是作为首选数据库。</p>
<h2 id="显示最新的项目列表"><a href="#显示最新的项目列表" class="headerlink" title="显示最新的项目列表"></a>显示最新的项目列表</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;下面这个语句常用来显示最新项目，随着数据多了，查询毫无疑问会越来越慢。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">SELECT * FROM foo WHERE ... ORDER BY time DESC LIMIT 10</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在Web应用中，“列出最新的回复”之类的查询非常普遍，这通常会带来可扩展性问题。这令人沮丧，因为项目本来就是按这个顺序被创建的，但要输出这个顺序却不得不进行排序操作。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;类似的问题就可以用Redis来解决。比如说，我们的一个Web应用想要列出用户贴出的最新20条评论。在最新的评论边上我们有一个“显示全部”的链接，点击后就可以获得更多的评论。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;我们假设数据库中的每条评论都有一个唯一的递增的ID字段。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;我们可以使用分页来制作主页和评论页，使用Redis的模板：</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;每次新评论发表时，我们会将它的ID添加到一个Redis列表：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">LPUSH latest.comments &lt;ID&gt;</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;我们将列表裁剪为指定长度，因此Redis只需要保存最新的5000条评论：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">LTRIM latest.comments 0 5000</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;每次我们需要获取最新评论的项目范围时，我们调用一个函数来完成（使用伪代码）：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">FUNCTION get_latest_comments(start,num_items): </div><div class="line">    id_list = redis.lrange(&amp;quot;latest.comments&amp;quot;,start,start+num_items-1) </div><div class="line">    IF id_list.length &amp;lt; num_items </div><div class="line">         id_list = SQL_DB(&amp;quot;SELECT ... ORDER BY time LIMIT ...&amp;quot;) </div><div class="line">    END </div><div class="line">    RETURN id_list </div><div class="line">END</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;这里我们做的很简单。在Redis中我们的最新ID使用了常驻缓存，这是一直更新的。但是我们做了限制不能超过5000个ID，因此我们的获取ID函数会一直询问Redis。只有在start/count参数超出了这个范围的时候，才需要去访问数据库。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;我们的系统不会像传统方式那样“刷新”缓存，Redis实例中的信息永远是一致的。SQL数据库（或是硬盘上的其他类型数据库）只是在用户需要获取“很远”的数据时才会被触发，而主页或第一个评论页是不会麻烦到硬盘上的数据库了。</p>
<h2 id="删除与过滤"><a href="#删除与过滤" class="headerlink" title="删除与过滤"></a>删除与过滤</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;我们可以使用LREM来删除评论。如果删除操作非常少，另一个选择是直接跳过评论条目的入口，报告说该评论已经不存在。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;有些时候你想要给不同的列表附加上不同的过滤器。如果过滤器的数量受到限制，你可以简单的为每个不同的过滤器使用不同的Redis列表。毕竟每个列表只有5000条项目，但Redis却能够使用非常少的内存来处理几百万条项目。</p>
<h2 id="排行榜相关"><a href="#排行榜相关" class="headerlink" title="排行榜相关"></a>排行榜相关</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;另一个很普遍的需求是各种数据库的数据并非存储在内存中，因此在按得分排序以及实时更新这些几乎每秒钟都需要更新的功能上数据库的性能不够理想。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;典型的比如那些在线游戏的排行榜，比如一个Facebook的游戏，根据得分你通常想要：</p>
<ul>
<li>列出前100名高分选手<br>-列出某用户当前的全球排名</li>
</ul>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;这些操作对于Redis来说小菜一碟，即使你有几百万个用户，每分钟都会有几百万个新的得分。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;模式是这样的，每次获得新得分时，我们用这样的代码：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">ZADD leaderboard &lt;score&gt; &lt;username&gt;</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;你可能用userID来取代username，这取决于你是怎么设计的。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;得到前100名高分用户很简单：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">ZREVRANGE leaderboard 0 99。</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;用户的全球排名也相似，只需要：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">ZRANK leaderboard &lt;username&gt;。</div></pre></td></tr></table></figure>
<h2 id="按照用户投票和时间排序"><a href="#按照用户投票和时间排序" class="headerlink" title="按照用户投票和时间排序"></a>按照用户投票和时间排序</h2><p>排行榜的一种常见变体模式就像Reddit或Hacker News用的那样，新闻按照类似下面的公式根据得分来排序：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">score = points / time^alpha</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;因此用户的投票会相应的把新闻挖出来，但时间会按照一定的指数将新闻埋下去。下面是我们的模式，当然算法由你决定。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;模式是这样的，开始时先观察那些可能是最新的项目，例如首页上的1000条新闻都是候选者，因此我们先忽视掉其他的，这实现起来很简单。</p>
<ul>
<li>每次新的新闻贴上来后，我们将ID添加到列表中，使用LPUSH + LTRIM，确保只取出最新的1000条项目。</li>
<li>有一项后台任务获取这个列表，并且持续的计算这1000条新闻中每条新闻的最终得分。计算结果由ZADD命令按照新的顺序填充生成列表，老新闻则被清除。这里的关键思路是排序工作是由后台任务来完成的。</li>
</ul>
<h2 id="过期项目处理"><a href="#过期项目处理" class="headerlink" title="过期项目处理"></a>过期项目处理</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;另一种常用的项目排序是按照时间排序。我们使用unix时间作为得分即可。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;模式如下：</p>
<ul>
<li>每次有新项目添加到我们的非Redis数据库时，我们把它加入到排序集合中。这时我们用的是时间属性，current_time和time_to_live。</li>
<li>另一项后台任务使用ZRANGE…SCORES查询排序集合，取出最新的10个项目。如果发现unix时间已经过期，则在数据库中删除条目。</li>
</ul>
<h2 id="计数"><a href="#计数" class="headerlink" title="计数"></a>计数</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis是一个很好的计数器，这要感谢INCRBY和其他相似命令。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;我相信你曾许多次想要给数据库加上新的计数器，用来获取统计或显示新信息，但是最后却由于写入敏感而不得不放弃它们。<br>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;好了，现在使用Redis就不需要再担心了。有了原子递增（atomic increment），你可以放心的加上各种计数，用GETSET重置，或者是让它们过期。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;例如这样操作：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">INCR user:&lt;id&gt; EXPIRE </div><div class="line">user:&lt;id&gt; 60</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;你可以计算出最近用户在页面间停顿不超过60秒的页面浏览量，当计数达到比如20时，就可以显示出某些条幅提示，或是其它你想显示的东西。</p>
<h2 id="特定时间内的特定项目"><a href="#特定时间内的特定项目" class="headerlink" title="特定时间内的特定项目"></a>特定时间内的特定项目</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;另一项对于其他数据库很难，但Redis做起来却轻而易举的事就是统计在某段特点时间里有多少特定用户访问了某个特定资源。比如我想要知道某些特定的注册用户或IP地址，他们到底有多少访问了某篇文章。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;每次我获得一次新的页面浏览时我只需要这样做：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">SADD page:day1:&lt;page_id&gt; &lt;user_id&gt;</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;当然你可能想用unix时间替换day1，比如time()-(time()%3600*24)等等。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;想知道特定用户的数量吗？只需要使用SCARD page:day1:<page_id>。</page_id></p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;需要测试某个特定用户是否访问了这个页面？SISMEMBER page:day1:<page_id>。</page_id></p>
<h2 id="实时分析正在发生的情况，用于数据统计与防止垃圾邮件等"><a href="#实时分析正在发生的情况，用于数据统计与防止垃圾邮件等" class="headerlink" title="实时分析正在发生的情况，用于数据统计与防止垃圾邮件等"></a>实时分析正在发生的情况，用于数据统计与防止垃圾邮件等</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;我们只做了几个例子，但如果你研究Redis的命令集，并且组合一下，就能获得大量的实时分析方法，有效而且非常省力。使用Redis原语命令，更容易实施垃圾邮件过滤系统或其他实时跟踪系统。</p>
<h2 id="Pub-Sub"><a href="#Pub-Sub" class="headerlink" title="Pub/Sub"></a>Pub/Sub</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis的Pub/Sub非常非常简单，运行稳定并且快速。支持模式匹配，能够实时订阅与取消频道。</p>
<h2 id="队列"><a href="#队列" class="headerlink" title="队列"></a>队列</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;你应该已经注意到像list push和list pop这样的Redis命令能够很方便的执行队列操作了，但能做的可不止这些：比如Redis还有list pop的变体命令，能够在列表为空时阻塞队列。</p>
<h2 id="缓存"><a href="#缓存" class="headerlink" title="缓存"></a>缓存</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis的缓存部分值得写一篇新文章，我这里只是简单的说一下。Redis能够替代memcached，让你的缓存从只能存储数据变得能够更新数据，因此你不再需要每次都重新生成数据了。</p>
<h2 id="Redis可以解决你的问题！"><a href="#Redis可以解决你的问题！" class="headerlink" title="Redis可以解决你的问题！"></a>Redis可以解决你的问题！</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;现在你就可以用上Redis，让用户感到更轻松，让你的系统变得不再复杂，让你的网站反应更快。你不需要改变现有的数据库结构，使用Redis给你的框架带来新的东西，来完成那些从前认为不可能做到/很难做到的，或是成本太高的任务。</p>

	

	

</article>




	<article>
	
		<h1><a href="/2017/10/12/Redis/10. Redis快速入门/">Redis快速入门</a></h1>
	
	<div class="article__infos">
		<span class="article__date">2017-10-12</span><br />
		
		
			<span class="article__tags">
			  	<a class="article__tag-link" href="/tags/Redis/">Redis</a>
			</span>
		
	</div>

	

	
		<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis是一个开源，高级的键值存储和一个适用的解决方案，用于构建高性能，可扩展的Web应用程序。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis有三个主要特点，使它优越于其它键值数据存储系统 -</p>
<ul>
<li>Redis将其数据库完全保存在内存中，仅使用磁盘进行持久化。</li>
<li>与其它键值数据存储相比，Redis有一组相对丰富的数据类型。</li>
<li>Redis可以将数据复制到任意数量的从机中。</li>
</ul>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis官方网站是：<a href="http://www.redis.io/" target="_blank" rel="external">http://www.redis.io/</a> ，如下：</p>
<p><figure class="figure"><img src="https://github.com/hcldirgit/image/blob/master/Redis%E5%BF%AB%E9%80%9F%E5%85%A5%E9%97%A8/01.png?raw=true" alt=""></figure></p>
<h2 id="Redis的优点"><a href="#Redis的优点" class="headerlink" title="Redis的优点"></a>Redis的优点</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;以下是Redis的一些优点。</p>
<ul>
<li>异常快 - Redis非常快，每秒可执行大约<code>110000</code>次的设置(<code>SET</code>)操作，每秒大约可执行<code>81000</code>次的读取/获取(<code>GET</code>)操作。</li>
<li>支持丰富的数据类型 - Redis支持开发人员常用的大多数数据类型，例如列表，集合，排序集和散列等等。这使得Redis很容易被用来解决各种问题，因为我们知道哪些问题可以更好使用地哪些数据类型来处理解决。</li>
<li>操作具有原子性 - 所有Redis操作都是原子操作，这确保如果两个客户端并发访问，Redis服务器能接收更新的值。</li>
<li>多实用工具 - Redis是一个多实用工具，可用于多种用例，如：缓存，消息队列(Redis本地支持发布/订阅)，应用程序中的任何短期数据，例如，web应用程序中的会话，网页命中计数等。</li>
</ul>
<h2 id="Redis与其他键值存储系统"><a href="#Redis与其他键值存储系统" class="headerlink" title="Redis与其他键值存储系统"></a>Redis与其他键值存储系统</h2><ul>
<li>Redis是键值数据库系统的不同进化路线，它的值可以包含更复杂的数据类型，可在这些数据类型上定义原子操作。</li>
<li>Redis是一个内存数据库，但在磁盘数据库上是持久的，因此它代表了一个不同的权衡，在这种情况下，在不能大于存储器(内存)的数据集的限制下实现非常高的写和读速度。</li>
<li>内存数据库的另一个优点是，它与磁盘上的相同数据结构相比，复杂数据结构在内存中存储表示更容易操作。 因此，Redis可以做很少的内部复杂性。</li>
</ul>
<h2 id="1-Redis环境安装配置"><a href="#1-Redis环境安装配置" class="headerlink" title="1.Redis环境安装配置"></a>1.Redis环境安装配置</h2><h3 id="在Ubuntu上安装Redis"><a href="#在Ubuntu上安装Redis" class="headerlink" title="在Ubuntu上安装Redis"></a>在Ubuntu上安装Redis</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;要在Ubuntu上安装Redis，打开终端并键入以下命令 -</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">[yiibai@ubuntu:~]$ sudo apt-get update </div><div class="line">[yiibai@ubuntu:~]$ sudo apt-get install redis-server</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;这将在Ubuntu机器上安装Redis。</p>
<h3 id="启动Redis"><a href="#启动Redis" class="headerlink" title="启动Redis"></a>启动Redis</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div></pre></td><td class="code"><pre><div class="line">[yiibai@ubuntu:~]$ redis-server</div><div class="line">[2988] 07 Feb 17:09:42.485 <span class="comment"># Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf</span></div><div class="line">[2988] 07 Feb 17:09:42.488 <span class="comment"># Unable to set the max number of files limit to 10032 (Operation not permitted), setting the max clients configuration to 3984.</span></div><div class="line">[2988] 07 Feb 17:09:42.490 <span class="comment"># Warning: 32 bit instance detected but no memory lim</span></div><div class="line">                _._</div><div class="line">           _.-``__ <span class="string">''</span>-._</div><div class="line">      _.-``    `.  `_.  <span class="string">''</span>-._           Redis 2.8.4 (00000000/0) 32 bit</div><div class="line">  .-`` .-```.  ```\/    _.,_ <span class="string">''</span>-._</div><div class="line"> (    <span class="string">'      ,       .-`  | `,    )     Running in stand alone mode</span></div><div class="line"><span class="string"> |`-._`-...-` __...-.``-._|'</span>` _.-<span class="string">'|     Port: 6379</span></div><div class="line"><span class="string"> |    `-._   `._    /     _.-'</span>    |     PID: 2988</div><div class="line">  `-._    `-._  `-./  _.-<span class="string">'    _.-'</span></div><div class="line"> |`-._`-._    `-.__.-<span class="string">'    _.-'</span>_.-<span class="string">'|</span></div><div class="line"><span class="string"> |    `-._`-._        _.-'</span>_.-<span class="string">'    |           http://redis.io</span></div><div class="line"><span class="string">  `-._    `-._`-.__.-'</span>_.-<span class="string">'    _.-'</span></div><div class="line"> |`-._`-._    `-.__.-<span class="string">'    _.-'</span>_.-<span class="string">'|</span></div><div class="line"><span class="string"> |    `-._`-._        _.-'</span>_.-<span class="string">'    |</span></div><div class="line"><span class="string">  `-._    `-._`-.__.-'</span>_.-<span class="string">'    _.-'</span></div><div class="line">      `-._    `-.__.-<span class="string">'    _.-'</span></div><div class="line">          `-._        _.-<span class="string">'</span></div><div class="line"><span class="string">              `-.__.-'</span></div><div class="line"></div><div class="line">[2988] 07 Feb 17:09:42.581 <span class="comment"># Server started, Redis version 2.8.4</span></div><div class="line">[2988] 07 Feb 17:09:42.582 <span class="comment"># WARNING overcommit_memory is set to 0! Background s                                                                                        ' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_m</span></div><div class="line">[2988] 07 Feb 17:09:42.582 * The server is now ready to accept connections on po</div></pre></td></tr></table></figure>
<h3 id="检查Redis是否正在工作"><a href="#检查Redis是否正在工作" class="headerlink" title="检查Redis是否正在工作"></a>检查Redis是否正在工作</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">[yiibai@ubuntu:~]$ redis-cli</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;这将打开一个redis提示，如下所示 </p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379&gt;</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在上面的提示中，<code>127.0.0.1</code>是计算机的IP地址，<code>6379</code>是运行<strong>Redis</strong>服务器的端口。 现在键入以下<code>PING</code>命令。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379&gt; ping </div><div class="line">PONG</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;这表明<strong>Redis</strong>已成功在计算机上安装了。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在Ubuntu上安装<strong>Redis桌面管理</strong></p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;要在Ubuntu上安装Redis桌面管理器，可从 <a href="http://redisdesktop.com/download" target="_blank" rel="external">http://redisdesktop.com/download</a> 下载该软件包，安装即可。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;打开下载的软件包并安装。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<strong>Redis桌面管理器</strong>将提供用于管理Redis的键和数据的UI。</p>
<h2 id="2-Redis配置"><a href="#2-Redis配置" class="headerlink" title="2. Redis配置"></a>2. Redis配置</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在Redis中，在Redis的根目录下有一个配置文件(redis.conf)。当然您可以通过Redis CONFIG命令获取和设置所有的Redis配置。</p>
<h3 id="语法"><a href="#语法" class="headerlink" title="语法"></a>语法</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;以下是Redis中的<code>CONFIG</code>命令的基本语法。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379&gt; CONFIG GET CONFIG_SETTING_NAME</div></pre></td></tr></table></figure>
<h3 id="示例"><a href="#示例" class="headerlink" title="示例"></a>示例</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379&gt; CONFIG GET loglevel  </div><div class="line">1) <span class="string">"loglevel"</span> </div><div class="line">2) <span class="string">"notice"</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;要获取所有配置设置，请使用<code>*</code>代替<code>CONFIG_SETTING_NAME</code></p>
<h3 id="示例-1"><a href="#示例-1" class="headerlink" title="示例"></a>示例</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div><div class="line">92</div><div class="line">93</div><div class="line">94</div><div class="line">95</div><div class="line">96</div><div class="line">97</div><div class="line">98</div><div class="line">99</div><div class="line">100</div><div class="line">101</div><div class="line">102</div><div class="line">103</div><div class="line">104</div><div class="line">105</div><div class="line">106</div><div class="line">107</div><div class="line">108</div><div class="line">109</div><div class="line">110</div><div class="line">111</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379&gt; CONFIG GET *</div><div class="line">  1) <span class="string">"dbfilename"</span></div><div class="line">  2) <span class="string">"dump.rdb"</span></div><div class="line">  3) <span class="string">"requirepass"</span></div><div class="line">  4) <span class="string">""</span></div><div class="line">  5) <span class="string">"masterauth"</span></div><div class="line">  6) <span class="string">""</span></div><div class="line">  7) <span class="string">"unixsocket"</span></div><div class="line">  8) <span class="string">""</span></div><div class="line">  9) <span class="string">"logfile"</span></div><div class="line"> 10) <span class="string">"/var/log/redis/redis-server.log"</span></div><div class="line"> 11) <span class="string">"pidfile"</span></div><div class="line"> 12) <span class="string">"/var/run/redis/redis-server.pid"</span></div><div class="line"> 13) <span class="string">"maxmemory"</span></div><div class="line"> 14) <span class="string">"3221225472"</span></div><div class="line"> 15) <span class="string">"maxmemory-samples"</span></div><div class="line"> 16) <span class="string">"3"</span></div><div class="line"> 17) <span class="string">"timeout"</span></div><div class="line"> 18) <span class="string">"0"</span></div><div class="line"> 19) <span class="string">"tcp-keepalive"</span></div><div class="line"> 20) <span class="string">"0"</span></div><div class="line"> 21) <span class="string">"auto-aof-rewrite-percentage"</span></div><div class="line"> 22) <span class="string">"100"</span></div><div class="line"> 23) <span class="string">"auto-aof-rewrite-min-size"</span></div><div class="line"> 24) <span class="string">"67108864"</span></div><div class="line"> 25) <span class="string">"hash-max-ziplist-entries"</span></div><div class="line"> 26) <span class="string">"512"</span></div><div class="line"> 27) <span class="string">"hash-max-ziplist-value"</span></div><div class="line"> 28) <span class="string">"64"</span></div><div class="line"> 29) <span class="string">"list-max-ziplist-entries"</span></div><div class="line"> 30) <span class="string">"512"</span></div><div class="line"> 31) <span class="string">"list-max-ziplist-value"</span></div><div class="line"> 32) <span class="string">"64"</span></div><div class="line"> 33) <span class="string">"set-max-intset-entries"</span></div><div class="line"> 34) <span class="string">"512"</span></div><div class="line"> 35) <span class="string">"zset-max-ziplist-entries"</span></div><div class="line"> 36) <span class="string">"128"</span></div><div class="line"> 37) <span class="string">"zset-max-ziplist-value"</span></div><div class="line"> 38) <span class="string">"64"</span></div><div class="line"> 39) <span class="string">"lua-time-limit"</span></div><div class="line"> 40) <span class="string">"5000"</span></div><div class="line"> 41) <span class="string">"slowlog-log-slower-than"</span></div><div class="line"> 42) <span class="string">"10000"</span></div><div class="line"> 43) <span class="string">"slowlog-max-len"</span></div><div class="line"> 44) <span class="string">"128"</span></div><div class="line"> 45) <span class="string">"port"</span></div><div class="line"> 46) <span class="string">"6379"</span></div><div class="line"> 47) <span class="string">"databases"</span></div><div class="line"> 48) <span class="string">"16"</span></div><div class="line"> 49) <span class="string">"repl-ping-slave-period"</span></div><div class="line"> 50) <span class="string">"10"</span></div><div class="line"> 51) <span class="string">"repl-timeout"</span></div><div class="line"> 52) <span class="string">"60"</span></div><div class="line"> 53) <span class="string">"repl-backlog-size"</span></div><div class="line"> 54) <span class="string">"1048576"</span></div><div class="line"> 55) <span class="string">"repl-backlog-ttl"</span></div><div class="line"> 56) <span class="string">"3600"</span></div><div class="line"> 57) <span class="string">"maxclients"</span></div><div class="line"> 58) <span class="string">"3984"</span></div><div class="line"> 59) <span class="string">"watchdog-period"</span></div><div class="line"> 60) <span class="string">"0"</span></div><div class="line"> 61) <span class="string">"slave-priority"</span></div><div class="line"> 62) <span class="string">"100"</span></div><div class="line"> 63) <span class="string">"min-slaves-to-write"</span></div><div class="line"> 64) <span class="string">"0"</span></div><div class="line"> 65) <span class="string">"min-slaves-max-lag"</span></div><div class="line"> 66) <span class="string">"10"</span></div><div class="line"> 67) <span class="string">"hz"</span></div><div class="line"> 68) <span class="string">"10"</span></div><div class="line"> 69) <span class="string">"no-appendfsync-on-rewrite"</span></div><div class="line"> 70) <span class="string">"no"</span></div><div class="line"> 71) <span class="string">"slave-serve-stale-data"</span></div><div class="line"> 72) <span class="string">"yes"</span></div><div class="line"> 73) <span class="string">"slave-read-only"</span></div><div class="line"> 74) <span class="string">"yes"</span></div><div class="line"> 75) <span class="string">"stop-writes-on-bgsave-error"</span></div><div class="line"> 76) <span class="string">"yes"</span></div><div class="line"> 77) <span class="string">"daemonize"</span></div><div class="line"> 78) <span class="string">"yes"</span></div><div class="line"> 79) <span class="string">"rdbcompression"</span></div><div class="line"> 80) <span class="string">"yes"</span></div><div class="line"> 81) <span class="string">"rdbchecksum"</span></div><div class="line"> 82) <span class="string">"yes"</span></div><div class="line"> 83) <span class="string">"activerehashing"</span></div><div class="line"> 84) <span class="string">"yes"</span></div><div class="line"> 85) <span class="string">"repl-disable-tcp-nodelay"</span></div><div class="line"> 86) <span class="string">"no"</span></div><div class="line"> 87) <span class="string">"aof-rewrite-incremental-fsync"</span></div><div class="line"> 88) <span class="string">"yes"</span></div><div class="line"> 89) <span class="string">"appendonly"</span></div><div class="line"> 90) <span class="string">"no"</span></div><div class="line"> 91) <span class="string">"dir"</span></div><div class="line"> 92) <span class="string">"/var/lib/redis"</span></div><div class="line"> 93) <span class="string">"maxmemory-policy"</span></div><div class="line"> 94) <span class="string">"noeviction"</span></div><div class="line"> 95) <span class="string">"appendfsync"</span></div><div class="line"> 96) <span class="string">"everysec"</span></div><div class="line"> 97) <span class="string">"save"</span></div><div class="line"> 98) <span class="string">"900 1 300 10 60 10000"</span></div><div class="line"> 99) <span class="string">"loglevel"</span></div><div class="line">100) <span class="string">"notice"</span></div><div class="line">101) <span class="string">"client-output-buffer-limit"</span></div><div class="line">102) <span class="string">"normal 0 0 0 slave 268435456 67108864 60 pubsub 33554432 8388608 60"</span></div><div class="line">103) <span class="string">"unixsocketperm"</span></div><div class="line">104) <span class="string">"0"</span></div><div class="line">105) <span class="string">"slaveof"</span></div><div class="line">106) <span class="string">""</span></div><div class="line">107) <span class="string">"notify-keyspace-events"</span></div><div class="line">108) <span class="string">""</span></div><div class="line">109) <span class="string">"bind"</span></div><div class="line">110) <span class="string">"127.0.0.1"</span></div></pre></td></tr></table></figure>
<h3 id="编辑配置"><a href="#编辑配置" class="headerlink" title="编辑配置"></a>编辑配置</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;要更新配置，可以直接编辑<code>redis.conf</code>文件，也可以通过<code>CONFIG set</code>命令更新配置。</p>
<h3 id="语法-1"><a href="#语法-1" class="headerlink" title="语法"></a>语法</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;以下是<code>CONFIG SET</code>命令的基本语法。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379&gt; CONFIG SET CONFIG_SETTING_NAME NEW_CONFIG_VALUE</div></pre></td></tr></table></figure>
<h3 id="示例-2"><a href="#示例-2" class="headerlink" title="示例"></a>示例</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379&gt; CONFIG SET loglevel <span class="string">"notice"</span> </div><div class="line">OK </div><div class="line">redis 127.0.0.1:6379&gt; CONFIG GET loglevel  </div><div class="line">1) <span class="string">"loglevel"</span> </div><div class="line">2) <span class="string">"notice"</span></div></pre></td></tr></table></figure>
<h2 id="3-Redis数据类型"><a href="#3-Redis数据类型" class="headerlink" title="3.Redis数据类型"></a>3.Redis数据类型</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis支持5种数据类型。</p>
<h3 id="字符串"><a href="#字符串" class="headerlink" title="字符串"></a>字符串</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis中的字符串是一个字节序列。Redis中的字符串是二进制安全的，这意味着它们的长度不由任何特殊的终止字符决定。因此，可以在一个字符串中存储高达512兆字节的任何内容。</p>
<h4 id="示例-3"><a href="#示例-3" class="headerlink" title="示例"></a>示例</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379&gt; <span class="built_in">set</span> name <span class="string">"yiibai.com"</span> </div><div class="line">OK </div><div class="line">redis 127.0.0.1:6379&gt; get name </div><div class="line"><span class="string">"yiibai.com"</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在上面的示例中，<code>set</code>和<code>get</code>是Redis命令，<code>name</code>是Redis中使用的键，<code>yiibai.com</code>是存储在Redis中的字符串的值。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;注 - Redis命令不区分大小写，如SET,Set和set都是同一个命令。字符串值的最大长度为 512MB。</p>
<h3 id="散列-哈希"><a href="#散列-哈希" class="headerlink" title="散列/哈希"></a>散列/哈希</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis散列/哈希(Hashes)是键值对的集合。Redis散列/哈希是字符串字段和字符串值之间的映射。因此，它们用于表示对象。</p>
<h4 id="示例-4"><a href="#示例-4" class="headerlink" title="示例"></a>示例</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379&gt; HMSET ukey username <span class="string">"yiibai"</span> password <span class="string">"passswd123"</span> points 200</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在上述示例中，散列/哈希数据类型用于存储包含用户的基本信息的用户对象。这里<code>HMSET</code>，<code>HGETALL</code>是Redis的命令，而<code>ukey</code>是键的名称。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;每个散列/哈希可以存储多达<code>2^32 - 1</code>个健-值对(超过<code>40</code>亿个)。</p>
<h3 id="列表"><a href="#列表" class="headerlink" title="列表"></a>列表</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis列表只是字符串列表，按插入顺序排序。您可以向Redis列表的头部或尾部添加元素。</p>
<h4 id="示例-5"><a href="#示例-5" class="headerlink" title="示例"></a>示例</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379&gt; lpush alist redis </div><div class="line">(<span class="built_in">integer</span>) 1 </div><div class="line">redis 127.0.0.1:6379&gt; lpush alist mongodb </div><div class="line">(<span class="built_in">integer</span>) 2 </div><div class="line">redis 127.0.0.1:6379&gt; lpush alist sqlite </div><div class="line">(<span class="built_in">integer</span>) 3 </div><div class="line">redis 127.0.0.1:6379&gt; lrange alist 0 10  </div><div class="line"></div><div class="line">1) <span class="string">"sqlite"</span> </div><div class="line">2) <span class="string">"mongodb"</span> </div><div class="line">3) <span class="string">"redis"</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;列表的最大长度为<code>2^32 - 1</code>个元素(<code>4294967295</code>，每个列表可容纳超过<code>40</code>亿个元素)。</p>
<h3 id="集合"><a href="#集合" class="headerlink" title="集合"></a>集合</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis集合是字符串的无序集合。在Redis中，您可以添加，删除和测试成员存在的时间O(1)复杂性。</p>
<h4 id="示例-6"><a href="#示例-6" class="headerlink" title="示例"></a>示例</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379&gt; sadd yiibailist redis </div><div class="line">(<span class="built_in">integer</span>) 1 </div><div class="line">redis 127.0.0.1:6379&gt; sadd yiibailist mongodb </div><div class="line">(<span class="built_in">integer</span>) 1 </div><div class="line">redis 127.0.0.1:6379&gt; sadd yiibailist sqlite </div><div class="line">(<span class="built_in">integer</span>) 1 </div><div class="line">redis 127.0.0.1:6379&gt; sadd yiibailist sqlite </div><div class="line">(<span class="built_in">integer</span>) 0 </div><div class="line">redis 127.0.0.1:6379&gt; smembers yiibailist  </div><div class="line"></div><div class="line">1) <span class="string">"sqlite"</span> </div><div class="line">2) <span class="string">"mongodb"</span> </div><div class="line">3) <span class="string">"redis"</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;注意 - 在上面的示例中，<code>sqlite</code>被添加了两次，但是由于集合的唯一属性，所以它只算添加一次。<br>一个集合中的最大成员数量为<code>2^32 - 1</code>(即<code>4294967295</code>，每个集合中元素数量可达<code>40</code>亿个)个。</p>
<h3 id="可排序集合"><a href="#可排序集合" class="headerlink" title="可排序集合"></a>可排序集合</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis可排序集合类似于Redis集合，是不重复的字符集合。 不同之处在于，排序集合的每个成员都与分数相关联，这个分数用于按最小分数到最大分数来排序的排序集合。虽然成员是唯一的，但分数值可以重复。</p>
<h4 id="示例-7"><a href="#示例-7" class="headerlink" title="示例"></a>示例</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379&gt; zadd yiibaiset 0 redis</div><div class="line">(<span class="built_in">integer</span>) 1 </div><div class="line">redis 127.0.0.1:6379&gt; zadd yiibaiset 0 mongodb</div><div class="line">(<span class="built_in">integer</span>) 1 </div><div class="line">redis 127.0.0.1:6379&gt; zadd yiibaiset 1 sqlite</div><div class="line">(<span class="built_in">integer</span>) 1 </div><div class="line">redis 127.0.0.1:6379&gt; zadd yiibaiset 1 sqlite</div><div class="line">(<span class="built_in">integer</span>) 0 </div><div class="line">redis 127.0.0.1:6379&gt; ZRANGEBYSCORE yiibaiset 0 1000  </div><div class="line"></div><div class="line">1) <span class="string">"mongodb"</span> </div><div class="line">2) <span class="string">"redis"</span> </div><div class="line">3) <span class="string">"sqlite"</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;因为 ‘<code>sqlite</code>‘ 的排序值是 1 ，其它两个元素的排序值是 0 ，所以 ‘<code>sqlite</code>‘ 排在最后一个位置上。</p>
<h2 id="4-Redis命令"><a href="#4-Redis命令" class="headerlink" title="4. Redis命令"></a>4. Redis命令</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis命令是用于在Redis服务器上执行一些操作。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;要在Redis服务器上运行命令，需要一个Redis客户端。Redis客户端在Redis包中有提供，这个包在我们前面的安装教程中就有安装过了。</p>
<h3 id="语法-2"><a href="#语法-2" class="headerlink" title="语法"></a>语法</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;以下是Redis客户端的基本语法。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">[yiibai@ubuntu:~]$ redis-cli</div></pre></td></tr></table></figure>
<h4 id="示例-8"><a href="#示例-8" class="headerlink" title="示例"></a>示例</h4><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;以下示例说明了如何启动Redis客户端。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;要启动Redis客户端，请打开终端并键入命令redis-cli。 这将连接到您的本地Redis服务器，现在可以运行任何的Redis命令了。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">[yiibai@ubuntu:~]<span class="variable">$redis</span>-cli </div><div class="line">redis 127.0.0.1:6379&gt; </div><div class="line">redis 127.0.0.1:6379&gt; PING  </div><div class="line">PONG</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在上面的示例中，连接到到在本地机器上运行的Redis服务器并执行<code>PING</code>命令，该命令检查服务器是否正在运行。</p>
<h3 id="在远程服务器上运行命令"><a href="#在远程服务器上运行命令" class="headerlink" title="在远程服务器上运行命令"></a>在远程服务器上运行命令</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;要在Redis远程服务器上运行命令，需要通过客户端redis-cli连接到服务器</p>
<h4 id="语法-3"><a href="#语法-3" class="headerlink" title="语法"></a>语法</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">[yiibai@ubuntu:~]$ redis-cli -h host -p port -a password</div></pre></td></tr></table></figure>
<h4 id="示例-9"><a href="#示例-9" class="headerlink" title="示例"></a>示例</h4><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;以下示例显示如何连接到Redis远程服务器，在主机(host)127.0.0.1，端口(port)6379上运行，并使用密码为 mypass。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">[yiibai@ubuntu:~]$ redis-cli -h 127.0.0.1 -p 6379 -a <span class="string">"mypass"</span> </div><div class="line">redis 127.0.0.1:6379&gt; </div><div class="line">redis 127.0.0.1:6379&gt; PING  </div><div class="line">PONG</div></pre></td></tr></table></figure>
<h2 id="5-Redis键命令"><a href="#5-Redis键命令" class="headerlink" title="5. Redis键命令"></a>5. Redis键命令</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis键命令用于管理Redis中的键。以下是使用redis键命令的语法。</p>
<h3 id="语法-4"><a href="#语法-4" class="headerlink" title="语法"></a>语法</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379&gt; COMMAND KEY_NAME</div></pre></td></tr></table></figure>
<h3 id="示例-10"><a href="#示例-10" class="headerlink" title="示例"></a>示例</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379&gt; SET akey redis</div><div class="line">OK </div><div class="line">redis 127.0.0.1:6379&gt; DEL akey</div><div class="line">(<span class="built_in">integer</span>) 1</div><div class="line">127.0.0.1:6379&gt; GET akey</div><div class="line">(nil)</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在上面的例子中，DEL是Redis的命令，而akey是键的名称。如果键被删除，则命令的输出将为(integer) 1，否则为(integer) 0。</p>
<h3 id="Redis键命令"><a href="#Redis键命令" class="headerlink" title="Redis键命令"></a>Redis键命令</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;下表列出了与键相关的一些基本命令。</p>
<table>
<thead>
<tr>
<th>编号</th>
<th>命</th>
<th>令描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>DEL key</td>
<td>此命令删除一个指定键(如果存在)。</td>
</tr>
<tr>
<td>2</td>
<td>DUMP key</td>
<td>此命令返回存储在指定键的值的序列化版本。</td>
</tr>
<tr>
<td>3</td>
<td>EXISTS key</td>
<td>此命令检查键是否存在。</td>
</tr>
<tr>
<td>4</td>
<td>EXPIRE key seconds</td>
<td>设置键在指定时间秒数之后到期/过期。</td>
</tr>
<tr>
<td>5</td>
<td>EXPIREAT key timestamp</td>
<td>设置在指定时间戳之后键到期/过期。这里的时间是Unix时间戳格式。</td>
</tr>
<tr>
<td>6</td>
<td>PEXPIRE key milliseconds</td>
<td>设置键的到期时间(以毫秒为单位)。</td>
</tr>
<tr>
<td>7</td>
<td>PEXPIREAT key milliseconds-timestamp</td>
<td>以Unix时间戳形式来设置键的到期时间(以毫秒为单位)。</td>
</tr>
<tr>
<td>8</td>
<td>KEYS pattern</td>
<td>查找与指定模式匹配的所有键。</td>
</tr>
<tr>
<td>9</td>
<td>MOVE key db</td>
<td>将键移动到另一个数据库。</td>
</tr>
<tr>
<td>10</td>
<td>PERSIST key</td>
<td>删除指定键的过期时间，得永生。</td>
</tr>
<tr>
<td>11</td>
<td>PTTL key</td>
<td>获取键的剩余到期时间。</td>
</tr>
<tr>
<td>12</td>
<td>RANDOMKEY</td>
<td>从Redis返回一个随机的键。</td>
</tr>
<tr>
<td>13</td>
<td>RENAME key newkey</td>
<td>更改键的名称。</td>
</tr>
<tr>
<td>14</td>
<td>PTTL key</td>
<td>获取键到期的剩余时间(以毫秒为单位)。</td>
</tr>
<tr>
<td>15</td>
<td>RENAMENX key newkey</td>
<td>如果新键不存在，重命名键。</td>
</tr>
<tr>
<td>16</td>
<td>TYPE key</td>
<td>返回存储在键中的值的数据类型。</td>
</tr>
</tbody>
</table>
<h2 id="6-Redis字符串"><a href="#6-Redis字符串" class="headerlink" title="6. Redis字符串"></a>6. Redis字符串</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis字符串命令用于管理Redis中的字符串值。以下是使用Redis字符串命令的语法。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379&gt; COMMAND KEY_NAME</div></pre></td></tr></table></figure>
<h3 id="示例-11"><a href="#示例-11" class="headerlink" title="示例"></a>示例</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379&gt; SET mykey <span class="string">"redis"</span> </div><div class="line">OK </div><div class="line">redis 127.0.0.1:6379&gt; GET mykey </div><div class="line"><span class="string">"redis"</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在上面的例子中，SET和GET是redis中的命令，而mykey是键的名称。</p>
<h3 id="Redis字符串命令"><a href="#Redis字符串命令" class="headerlink" title="Redis字符串命令"></a>Redis字符串命令</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;下表列出了一些用于在Redis中管理字符串的基本命令。</p>
<table>
<thead>
<tr>
<th>编号</th>
<th>命令</th>
<th>描述说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>SET key value</td>
<td>此命令设置指定键的值。</td>
</tr>
<tr>
<td>2</td>
<td>GET key</td>
<td>获取指定键的值。</td>
</tr>
<tr>
<td>3</td>
<td>GETRANGE key start end</td>
<td>获取存储在键上的字符串的子字符串。</td>
</tr>
<tr>
<td>4</td>
<td>GETSET key value</td>
<td>设置键的字符串值并返回其旧值。</td>
</tr>
<tr>
<td>5</td>
<td>GETBIT key offset</td>
<td>返回在键处存储的字符串值中偏移处的位值。</td>
</tr>
<tr>
<td>6</td>
<td>MGET key1 [key2..]</td>
<td>获取所有给定键的值</td>
</tr>
<tr>
<td>7</td>
<td>SETBIT key offset value</td>
<td>存储在键上的字符串值中设置或清除偏移处的位</td>
</tr>
<tr>
<td>8</td>
<td>SETEX key seconds value</td>
<td>使用键和到期时间来设置值</td>
</tr>
<tr>
<td>9</td>
<td>SETNX key value</td>
<td>设置键的值，仅当键不存在时</td>
</tr>
<tr>
<td>10</td>
<td>SETRANGE key offset value</td>
<td>在指定偏移处开始的键处覆盖字符串的一部分</td>
</tr>
<tr>
<td>11</td>
<td>STRLEN key</td>
<td>获取存储在键中的值的长度</td>
</tr>
<tr>
<td>12</td>
<td>MSET key value [key value …]</td>
<td>为多个键分别设置它们的值</td>
</tr>
<tr>
<td>13</td>
<td>MSETNX key value [key value …]</td>
<td>为多个键分别设置它们的值，仅当键不存在时</td>
</tr>
<tr>
<td>14</td>
<td>PSETEX key milliseconds value</td>
<td>设置键的值和到期时间(以毫秒为单位)</td>
</tr>
<tr>
<td>15</td>
<td>INCR key</td>
<td>将键的整数值增加1</td>
</tr>
<tr>
<td>16</td>
<td>INCRBY key increment</td>
<td>将键的整数值按给定的数值增加</td>
</tr>
<tr>
<td>17</td>
<td>INCRBYFLOAT key increment</td>
<td>将键的浮点值按给定的数值增加</td>
</tr>
<tr>
<td>18</td>
<td>DECR key</td>
<td>将键的整数值减1</td>
</tr>
<tr>
<td>19</td>
<td>DECRBY key decrement</td>
<td>按给定数值减少键的整数值</td>
</tr>
<tr>
<td>20</td>
<td>APPEND key value</td>
<td>将指定值附加到键</td>
</tr>
</tbody>
</table>
<h2 id="7-Redis哈希"><a href="#7-Redis哈希" class="headerlink" title="7. Redis哈希"></a>7. Redis哈希</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis Hashes是字符串字段和字符串值之间的映射(类似于PHP中的数组类型)。 因此，它们是表示对象的完美数据类型。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在Redis中，每个哈希(散列)可以存储多达4亿个键-值对。</p>
<h3 id="示例-12"><a href="#示例-12" class="headerlink" title="示例"></a>示例</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379&gt; HMSET myhash name <span class="string">"redis tutorial"</span> </div><div class="line">description <span class="string">"redis basic commands for caching"</span> likes 20 visitors 23000 </div><div class="line">OK </div><div class="line">127.0.0.1:6379&gt; HGETALL myhash</div><div class="line">1) <span class="string">"field1"</span></div><div class="line">2) <span class="string">"Hello"</span></div><div class="line">3) <span class="string">"field2"</span></div><div class="line">4) <span class="string">"World"</span></div><div class="line">5) <span class="string">"name"</span></div><div class="line">6) <span class="string">"redis tutorial"</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在上面的例子中，在名称为’myhash‘的哈希中设置了Redis教程的详细信息(名称，描述，喜欢，访问者)。</p>
<h2 id="8-Redis列表"><a href="#8-Redis列表" class="headerlink" title="8. Redis列表"></a>8. Redis列表</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis列表只是字符串列表，按插入顺序排序。可以在列表的头部或尾部添加Redis列表中的元素。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;列表的最大长度为<code>2^32 - 1</code>个元素(即<code>4294967295</code>，每个列表可存储超过<code>40</code>亿个元素)。</p>
<h3 id="示例-13"><a href="#示例-13" class="headerlink" title="示例"></a>示例</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379&gt; LPUSH mylist <span class="string">"redis"</span> </div><div class="line">(<span class="built_in">integer</span>) 1 </div><div class="line">redis 127.0.0.1:6379&gt; LPUSH mylist <span class="string">"mongodb"</span></div><div class="line">(<span class="built_in">integer</span>) 2 </div><div class="line">redis 127.0.0.1:6379&gt; LPUSH mylist <span class="string">"mysql"</span></div><div class="line">(<span class="built_in">integer</span>) 3 </div><div class="line">redis 127.0.0.1:6379&gt; LRANGE mylist 0 10  </div><div class="line">1) <span class="string">"mysql"</span> </div><div class="line">2) <span class="string">"mongodb"</span> </div><div class="line">3) <span class="string">"redis"</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在上面的示例中，通过命令<code>LPUSH</code>将三个值插入到名称为“<code>mylist</code>”的Redis列表中。</p>
<h2 id="8-Redis集合"><a href="#8-Redis集合" class="headerlink" title="8. Redis集合"></a>8. Redis集合</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis集合是唯一字符串的无序集合。 唯一值表示集合中不允许键中有重复的数据。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在Redis中设置添加，删除和测试成员的存在(恒定时间O(1)，而不考虑集合中包含的元素数量)。列表的最大长度为2^32 - 1个元素(即4294967295，每组集合超过40亿个元素)。</p>
<h3 id="示例-14"><a href="#示例-14" class="headerlink" title="示例"></a>示例</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379&gt; SADD myset <span class="string">"redis"</span> </div><div class="line">(<span class="built_in">integer</span>) 1 </div><div class="line">redis 127.0.0.1:6379&gt; SADD myset <span class="string">"mongodb"</span> </div><div class="line">(<span class="built_in">integer</span>) 1 </div><div class="line">redis 127.0.0.1:6379&gt; SADD myset <span class="string">"mysql"</span> </div><div class="line">(<span class="built_in">integer</span>) 1 </div><div class="line">redis 127.0.0.1:6379&gt; SADD myset <span class="string">"mysql"</span> </div><div class="line">(<span class="built_in">integer</span>) 0 </div><div class="line">redis 127.0.0.1:6379&gt; SMEMBERS <span class="string">"myset"</span>  </div><div class="line">1) <span class="string">"mysql"</span> </div><div class="line">2) <span class="string">"mongodb"</span> </div><div class="line">3) <span class="string">"redis"</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在上面的示例中，通过命令<code>SADD</code>将三个值插入到名称为“<code>myset</code>”的Redis集合中。</p>
<h2 id="9-Redis发送订阅"><a href="#9-Redis发送订阅" class="headerlink" title="9. Redis发送订阅"></a>9. Redis发送订阅</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis发布订阅(pub/sub)是一种消息通信模式：发送者(pub)发送消息，订阅者(sub)接收消息。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis 发布订阅(pub/sub)实现了消息系统，发送者(在redis术语中称为发布者)在接收者(订阅者)接收消息时发送消息。传送消息的链路称为信道。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在Redis中，客户端可以订阅任意数量的信道。</p>
<h3 id="示例-15"><a href="#示例-15" class="headerlink" title="示例"></a>示例</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;以下示例说明了发布用户概念的工作原理。 在以下示例中，一个客户端订阅名为“<code>redisChat</code>”的信道。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379&gt; SUBSCRIBE redisChat  </div><div class="line">Reading messages... (press Ctrl-C to quit) </div><div class="line">1) <span class="string">"subscribe"</span> </div><div class="line">2) <span class="string">"redisChat"</span> </div><div class="line">3) (<span class="built_in">integer</span>) 1</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;现在，两个客户端在名称为“<code>redisChat</code>”的相同信道上发布消息，并且上述订阅的客户端接收消息。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379&gt; PUBLISH redisChat <span class="string">"Redis is a great caching technique"</span>  </div><div class="line">(<span class="built_in">integer</span>) 1  </div><div class="line">redis 127.0.0.1:6379&gt; PUBLISH redisChat <span class="string">"Learn redis by yiibai"</span>  </div><div class="line">(<span class="built_in">integer</span>) 1   </div><div class="line">1) <span class="string">"message"</span> </div><div class="line">2) <span class="string">"redisChat"</span> </div><div class="line">3) <span class="string">"Redis is a great caching technique"</span> </div><div class="line">1) <span class="string">"message"</span> </div><div class="line">2) <span class="string">"redisChat"</span> </div><div class="line">3) <span class="string">"Learn redis by yiibai"</span></div></pre></td></tr></table></figure>
<h2 id="10-Redis事务"><a href="#10-Redis事务" class="headerlink" title="10. Redis事务"></a>10. Redis事务</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis事务允许在单个步骤中执行一组命令。以下是事务的两个属性：</p>
<ul>
<li>事务中的所有命令作为单个隔离操作并按顺序执行。不可以在执行Redis事务的中间向另一个客户端发出的请求。</li>
<li>Redis事务也是原子的。原子意味着要么处理所有命令，要么都不处理。</li>
</ul>
<h3 id="语法示例"><a href="#语法示例" class="headerlink" title="语法示例"></a>语法示例</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis事务由命令<code>MULTI</code>命令启动，然后需要传递一个应该在事务中执行的命令列表，然后整个事务由<code>EXEC</code>命令执行。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379&gt; MULTI </div><div class="line">OK </div><div class="line">List of commands here </div><div class="line">redis 127.0.0.1:6379&gt; EXEC</div></pre></td></tr></table></figure>
<h3 id="示例-16"><a href="#示例-16" class="headerlink" title="示例"></a>示例</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;以下示例说明了如何启动和执行Redis事务。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379&gt; MULTI </div><div class="line">OK </div><div class="line">redis 127.0.0.1:6379&gt; SET mykey <span class="string">"redis"</span> </div><div class="line">QUEUED </div><div class="line">redis 127.0.0.1:6379&gt; GET mykey </div><div class="line">QUEUED </div><div class="line">redis 127.0.0.1:6379&gt; INCR visitors </div><div class="line">QUEUED </div><div class="line">redis 127.0.0.1:6379&gt; EXEC  </div><div class="line">1) OK </div><div class="line">2) <span class="string">"redis"</span> </div><div class="line">3) (<span class="built_in">integer</span>) 1</div></pre></td></tr></table></figure>
<h2 id="11-Redis脚本"><a href="#11-Redis脚本" class="headerlink" title="11. Redis脚本"></a>11. Redis脚本</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis脚本用于使用Lua解释器来执行脚本。从Redis 2.6.0版开始内置到Redis中。使用脚本的命令是<strong>EVAL</strong>命令。</p>
<h3 id="语法-5"><a href="#语法-5" class="headerlink" title="语法"></a>语法</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;以下是<code>EVAL</code>命令的基本语法。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379&gt; EVAL script numkeys key [key ...] arg [arg ...]</div></pre></td></tr></table></figure>
<h3 id="示例-17"><a href="#示例-17" class="headerlink" title="示例"></a>示例</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;以下示例说明了Redis脚本的工作原理。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379&gt; EVAL <span class="string">"return &#123;KEYS[1],KEYS[2],ARGV[1],ARGV[2]&#125;"</span> 2 key1 </div><div class="line">key2 first second  </div><div class="line">1) <span class="string">"key1"</span> </div><div class="line">2) <span class="string">"key2"</span> </div><div class="line">3) <span class="string">"first"</span> </div><div class="line">4) <span class="string">"second"</span></div></pre></td></tr></table></figure>
<h2 id="12-Redis连接"><a href="#12-Redis连接" class="headerlink" title="12. Redis连接"></a>12. Redis连接</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis中的连接命令基本上是用于管理与Redis服务器的客户端连接。</p>
<h3 id="160-160-160-160-160-160-160-160-示例"><a href="#160-160-160-160-160-160-160-160-示例" class="headerlink" title="&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;示例"></a>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;示例</h3><p>以下示例说明客户端如何向Redis服务器验证自身，并检查服务器是否正在运行。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379&gt; AUTH <span class="string">"password"</span> </div><div class="line">OK </div><div class="line">redis 127.0.0.1:6379&gt; PING </div><div class="line">PONG</div></pre></td></tr></table></figure>
<h3 id="Redis连接命令"><a href="#Redis连接命令" class="headerlink" title="Redis连接命令"></a>Redis连接命令</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;下表列出了与Redis连接相关的一些基本命令。</p>
<table>
<thead>
<tr>
<th>序号</th>
<th>命令</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>AUTH password</td>
<td>使用给定的密码验证服务器</td>
</tr>
<tr>
<td>2</td>
<td>ECHO message</td>
<td>打印给定的字符串信息</td>
</tr>
<tr>
<td>3</td>
<td>PING</td>
<td>检查服务器是否正在运行</td>
</tr>
<tr>
<td>4</td>
<td>QUIT</td>
<td>关闭当前连接</td>
</tr>
<tr>
<td>5</td>
<td>SELECT index</td>
<td>更改当前连接的所选数据库</td>
</tr>
</tbody>
</table>
<h2 id="13-Redis服务器"><a href="#13-Redis服务器" class="headerlink" title="13. Redis服务器"></a>13. Redis服务器</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis服务器命令基本上是用于管理Redis服务器。</p>
<h3 id="示例-18"><a href="#示例-18" class="headerlink" title="示例"></a>示例</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;以下示例说明了如何获取有关服务器的所有统计信息和信息。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div></pre></td><td class="code"><pre><div class="line">127.0.0.1:6379&gt; info</div><div class="line"><span class="comment"># Server</span></div><div class="line">redis_version:2.8.4</div><div class="line">redis_git_sha1:00000000</div><div class="line">redis_git_dirty:0</div><div class="line">redis_build_id:8f6097d7914679ca</div><div class="line">redis_mode:standalone</div><div class="line">os:Linux 3.19.0-25-generic i686</div><div class="line">arch_bits:32</div><div class="line">multiplexing_api:epoll</div><div class="line">gcc_version:4.8.2</div><div class="line">process_id:1004</div><div class="line">run_id:1e53acea2aa628199c4e438a3ed815d96eebc036</div><div class="line">tcp_port:6379</div><div class="line">uptime_in_seconds:888450</div><div class="line">uptime_in_days:10</div><div class="line">hz:10</div><div class="line">lru_clock:1861984</div><div class="line">config_file:/etc/redis/redis.conf</div><div class="line"></div><div class="line"><span class="comment"># Clients</span></div><div class="line">connected_clients:1</div><div class="line">client_longest_output_list:0</div><div class="line">client_biggest_input_buf:0</div><div class="line">blocked_clients:0</div><div class="line"></div><div class="line"><span class="comment"># Memory</span></div><div class="line">used_memory:424872</div><div class="line">used_memory_human:414.91K</div><div class="line">used_memory_rss:6709248</div><div class="line">used_memory_peak:424464</div><div class="line">used_memory_peak_human:414.52K</div><div class="line">used_memory_lua:22528</div><div class="line">mem_fragmentation_ratio:15.79</div><div class="line">mem_allocator:jemalloc-3.4.1</div><div class="line"></div><div class="line"><span class="comment"># Persistence</span></div><div class="line">loading:0</div><div class="line">rdb_changes_since_last_save:0</div><div class="line">rdb_bgsave_in_progress:0</div><div class="line">rdb_last_save_time:1486607123</div><div class="line">rdb_last_bgsave_status:ok</div><div class="line">rdb_last_bgsave_time_sec:0</div><div class="line">rdb_current_bgsave_time_sec:-1</div><div class="line">aof_enabled:0</div><div class="line">aof_rewrite_in_progress:0</div><div class="line">aof_rewrite_scheduled:0</div><div class="line">aof_last_rewrite_time_sec:-1</div><div class="line">aof_current_rewrite_time_sec:-1</div><div class="line">aof_last_bgrewrite_status:ok</div><div class="line"></div><div class="line"><span class="comment"># Stats</span></div><div class="line">total_connections_received:1</div><div class="line">total_commands_processed:263</div><div class="line">instantaneous_ops_per_sec:0</div><div class="line">rejected_connections:0</div><div class="line">sync_full:0</div><div class="line">sync_partial_ok:0</div><div class="line">sync_partial_err:0</div><div class="line">expired_keys:0</div><div class="line">evicted_keys:0</div><div class="line">keyspace_hits:257</div><div class="line">keyspace_misses:0</div><div class="line">pubsub_channels:0</div><div class="line">pubsub_patterns:0</div><div class="line">latest_fork_usec:4793</div><div class="line"></div><div class="line"><span class="comment"># Replication</span></div><div class="line">role:master</div><div class="line">connected_slaves:0</div><div class="line">master_repl_offset:0</div><div class="line">repl_backlog_active:0</div><div class="line">repl_backlog_size:1048576</div><div class="line">repl_backlog_first_byte_offset:0</div><div class="line">repl_backlog_histlen:0</div><div class="line"></div><div class="line"><span class="comment"># CPU</span></div><div class="line">used_cpu_sys:24.65</div><div class="line">used_cpu_user:15.84</div><div class="line">used_cpu_sys_children:0.08</div><div class="line">used_cpu_user_children:0.00</div><div class="line"></div><div class="line"><span class="comment"># Keyspace</span></div><div class="line">db0:keys=14,expires=0,avg_ttl=0</div><div class="line">db1:keys=1,expires=0,avg_ttl=0</div><div class="line">127.0.0.1:6379&gt;</div></pre></td></tr></table></figure>
<h2 id="14-Redis备份"><a href="#14-Redis备份" class="headerlink" title="14. Redis备份"></a>14. Redis备份</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis数据库可以使用安全的方案，使得进行连接的任何客户端在执行命令之前都需要进行身份验证。要保护Redis安全，需要在配置文件中设置密码。</p>
<h3 id="示例-19"><a href="#示例-19" class="headerlink" title="示例"></a>示例</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;下面的示例显示了保护Redis实例的步骤。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">127.0.0.1:6379&gt; CONFIG get requirepass </div><div class="line">1) <span class="string">"requirepass"</span> </div><div class="line">2) <span class="string">""</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;默认情况下，此属性为空，这表示还没有为此实例设置密码。您可以通过执行以下命令更改此属性。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">127.0.0.1:6379&gt; CONFIG <span class="built_in">set</span> requirepass <span class="string">"yiibai"</span> </div><div class="line">OK </div><div class="line">127.0.0.1:6379&gt; CONFIG get requirepass </div><div class="line">1) <span class="string">"requirepass"</span> </div><div class="line">2) <span class="string">"yiibai"</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;设置密码后，如果任何客户端运行命令而不进行身份验证，则会返回一个<strong>(error) NOAUTH Authentication required</strong>.的错误信息。 因此，客户端需要使用AUTH命令来验证。</p>
<h3 id="语法-6"><a href="#语法-6" class="headerlink" title="语法"></a>语法</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;以下是AUTH命令的基本语法。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">127.0.0.1:6379&gt; AUTH password</div></pre></td></tr></table></figure>
<h3 id="示例-20"><a href="#示例-20" class="headerlink" title="示例"></a>示例</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">127.0.0.1:6379&gt; AUTH <span class="string">"yiibai"</span> </div><div class="line">OK </div><div class="line">127.0.0.1:6379&gt; SET mykey <span class="string">"Test value"</span> </div><div class="line">OK </div><div class="line">127.0.0.1:6379&gt; GET mykey </div><div class="line"><span class="string">"Test value"</span></div></pre></td></tr></table></figure>
<h2 id="15-Redis客户端连接"><a href="#15-Redis客户端连接" class="headerlink" title="15. Redis客户端连接"></a>15. Redis客户端连接</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis在配置的监听TCP端口和Unix套接字上等待和接受客户端的连接(如果已启用)。 当接受新的客户端连接时，执行以下操作 </p>
<ul>
<li>由于Redis使用复用和非阻塞I/O，因此客户端套接字处于非阻塞状态。</li>
<li>设置<code>TCP_NODELAY</code>选项是为了确保连接不延迟。</li>
<li>创建可读文件事件，以便Redis能够在套接字上读取新数据时收集客户端查询。</li>
</ul>
<h3 id="最大客户数"><a href="#最大客户数" class="headerlink" title="最大客户数"></a>最大客户数</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在Redis配置文件(<code>redis.conf</code>)中，有一个名称为<code>maxclients</code>的属性，它描述了可以连接到Redis的客户端的最大数量。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;以下是命令的基本语法。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">127.0.0.1:6379&gt; config get maxclients</div><div class="line">1) <span class="string">"maxclients"</span></div><div class="line">2) <span class="string">"3984"</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;默认情况下，此属性设置为10000(取决于操作系统的文件描述符限制的最大数量)，但您可以更改此属性。</p>
<h3 id="示例-21"><a href="#示例-21" class="headerlink" title="示例"></a>示例</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在以下示例中，我们已将客户端的最大数目设置为100000，并启动服务器。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">yiibai@ubuntu:~$ redis-server --maxclients 100000</div></pre></td></tr></table></figure>
<h3 id="客户端命令"><a href="#客户端命令" class="headerlink" title="客户端命令"></a>客户端命令</h3><table>
<thead>
<tr>
<th>编号</th>
<th>命令</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>CLIENT LIST</td>
<td>返回连接到Redis服务器的客户端列表</td>
</tr>
<tr>
<td>2</td>
<td>CLIENT SETNAME</td>
<td>为当前连接分配/设置新的名称</td>
</tr>
<tr>
<td>3</td>
<td>CLIENT GETNAME</td>
<td>返回由CLIENT SETNAME设置的当前连接的名称</td>
</tr>
<tr>
<td>4</td>
<td>CLIENT PAUSE</td>
<td>这是一个连接控制命令，能够将所有Redis客户端按指定的时间量(以毫秒为单位)挂起</td>
</tr>
<tr>
<td>5</td>
<td>CLIENT KILL</td>
<td>此命令关闭指定的客户端连接。</td>
</tr>
</tbody>
</table>
<h2 id="16-Redis管道"><a href="#16-Redis管道" class="headerlink" title="16. Redis管道"></a>16. Redis管道</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis是一个TCP服务器，支持请求/响应协议。 在Redis中，请求通过以下步骤完成：</p>
<ul>
<li>客户端向服务器发送查询，并从套接字读取，通常以阻塞的方式，用于服务器响应。</li>
<li>服务器处理命令并将响应发送回客户端。</li>
</ul>
<h3 id="管道的意义"><a href="#管道的意义" class="headerlink" title="管道的意义"></a>管道的意义</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;管道的基本含义是，客户端可以向服务器发送多个请求，而不必等待回复，并最终在一个步骤中读取回复。</p>
<h3 id="示例-22"><a href="#示例-22" class="headerlink" title="示例"></a>示例</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;要检查Redis管道，只需启动Redis实例，并在终端中键入以下命令。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">$(<span class="built_in">echo</span> -en <span class="string">"PING\r\n SET tutorial redis\r\nGET tutorial\r\nINCR </span></div><div class="line"><span class="string">visitor\r\nINCR visitor\r\nINCR visitor\r\n"</span>; sleep 10) | nc localhost 6379  </div><div class="line">+PONG </div><div class="line">+OK </div><div class="line">redis </div><div class="line">:1 </div><div class="line">:2 </div><div class="line">:3</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在上面的例子中，我们将使用PING命令检查Redis连接。这里设置了一个名称为tutorial的字符串，值为redis。 然后得到键值，并增加 visitor 数量三次。 在结果中，我们可以看到所有命令都提交到Redis一次，Redis在一个步骤中提供所有命令的输出。</p>
<h3 id="管道的好处"><a href="#管道的好处" class="headerlink" title="管道的好处"></a>管道的好处</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;这种技术的好处是大大提高了协议性能。通过管道从连接到本地主机速度增加五倍，因特网连接的至少快一百倍。</p>
<h2 id="17-Redis分区"><a href="#17-Redis分区" class="headerlink" title="17. Redis分区"></a>17. Redis分区</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;分区是将数据拆分为多个Redis实例的过程，因此每个实例只包含一部分键。</p>
<h3 id="分区的优点"><a href="#分区的优点" class="headerlink" title="分区的优点"></a>分区的优点</h3><ul>
<li>它允许更大的数据库，使用更多计算机的内存总和。如果没有分区，则限制为单个计算机可以支持的内存量。</li>
<li>它允许将计算能力扩展到多个核心和多个计算机，并将网络带宽扩展到多个计算机和网络适配器。</li>
</ul>
<h3 id="分区的缺点"><a href="#分区的缺点" class="headerlink" title="分区的缺点"></a>分区的缺点</h3><ul>
<li>通常不支持涉及多个键的操作。 例如，如果两个集合存储在映射到不同Redis实例的键中，则不能执行两个集合之间的交集操作。</li>
<li>不能使用涉及多个键的Redis事务。</li>
<li>分区粒度是关键，因此不可能使用单个巨大的键(如非常大的排序集合)来分割数据集。</li>
<li>使用分区时，数据处理更复杂。 例如，必须处理多个RDB/AOF文件，并获得数据的备份，您需要聚合来自多个实例和主机的持久性文件。</li>
<li>添加和删除容量可能很复杂。 例如，Redis Cluster支持大多数透明的数据重新平衡，具有在运行时添加和删除节点的能力。但是，其他系统(如客户端分区和代理)不支持此功能。但可以使用一种叫作Presharding的技术来处理这方面的问题。</li>
</ul>
<h3 id="分区类型"><a href="#分区类型" class="headerlink" title="分区类型"></a>分区类型</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis中有两种类型的分区。假设有四个Redis实例：<code>R0</code>，<code>R1</code>，<code>R2</code>，<code>R3</code>以许多代表用户的键，如<code>user：1</code>，<code>user：2</code>，…等等。</p>
<h3 id="范围分区"><a href="#范围分区" class="headerlink" title="范围分区"></a>范围分区</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;范围分区通过将对象的范围映射到特定的Redis实例来实现。假设在上面示例中，从ID 0到ID 10000的用户将进入实例R0，而从ID 10001到ID 20000的用户将进入实例R1，以此类推。</p>
<h3 id="哈希分区"><a href="#哈希分区" class="headerlink" title="哈希分区"></a>哈希分区</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在这种类型的分区中，使用散列函数(例如，模函数)将键转换成数字，然后将数据存储在不同的Redis实例中。</p>
<h2 id="18-Java连接Redis"><a href="#18-Java连接Redis" class="headerlink" title="18. Java连接Redis"></a>18. Java连接Redis</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在Java程序中使用Redis之前，需要确保在机器上安装了Redis的Java驱动程序和Java环境。可以先在将Java电脑上并配置好环境。</p>
<h3 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;现在，让我们看看如何设置Redis Java驱动程序。<br>-下载<code>jedis.jar</code> - <a href="http://repo1.maven.org/maven2/redis/clients/jedis/2.1.0/jedis-2.1.0-sources.jar" target="_blank" rel="external">http://repo1.maven.org/maven2/redis/clients/jedis/2.1.0/jedis-2.1.0-sources.jar</a> ，确保下载的<code>jedis.jar</code>是最新版本。</p>
<ul>
<li>将<code>jedis.jar</code>包含到类路径中。</li>
</ul>
<h3 id="Java连接到Redis服务器"><a href="#Java连接到Redis服务器" class="headerlink" title="Java连接到Redis服务器"></a>Java连接到Redis服务器</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;请参考以下一个简单的示例代码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">import</span> redis.clients.jedis.Jedis; </div><div class="line"></div><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RedisJava</span> </span>&#123; </div><div class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123; </div><div class="line">      <span class="comment">//Connecting to Redis server on localhost </span></div><div class="line">      Jedis jedis = <span class="keyword">new</span> Jedis(<span class="string">"localhost"</span>); </div><div class="line">      System.out.println(<span class="string">"Connection to server sucessfully"</span>); </div><div class="line">      <span class="comment">//check whether server is running or not </span></div><div class="line">      System.out.println(<span class="string">"Server is running: "</span>+jedis.ping()); </div><div class="line">   &#125; </div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;现在，编译并运行上面的程序来测试与Redis服务器的连接。可以根据需要更改路径。假设<code>jedis.jar</code>的当前版本在当前路径中可以使用。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;执行上面代码，将生成以下结果 -</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">$javac RedisJava.java </div><div class="line">$java RedisJava </div><div class="line">Connection to server sucessfully </div><div class="line">Server is running: PONG</div></pre></td></tr></table></figure>
<h3 id="Redis-Java字符串示例"><a href="#Redis-Java字符串示例" class="headerlink" title="Redis Java字符串示例"></a>Redis Java字符串示例</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">import</span> redis.clients.jedis.Jedis; </div><div class="line"></div><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RedisStringJava</span> </span>&#123; </div><div class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123; </div><div class="line">      <span class="comment">//Connecting to Redis server on localhost </span></div><div class="line">      Jedis jedis = <span class="keyword">new</span> Jedis(<span class="string">"localhost"</span>); </div><div class="line">      System.out.println(<span class="string">"Connection to server sucessfully"</span>); </div><div class="line">      <span class="comment">//set the data in redis string </span></div><div class="line">      jedis.set(<span class="string">"tutorial-name"</span>, <span class="string">"Redis tutorial"</span>); </div><div class="line">      <span class="comment">// Get the stored data and print it </span></div><div class="line">      System.out.println(<span class="string">"Stored string in redis:: "</span>+ jedis.get(<span class="string">"tutorialname"</span>)); </div><div class="line">   &#125; </div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;执行上面代码，将生成以下结果</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">$javac RedisStringJava.java </div><div class="line">$java RedisStringJava </div><div class="line">Connection to server sucessfully </div><div class="line">Stored string in redis:: Redis tutorial</div></pre></td></tr></table></figure>
<h3 id="Redis-Java列表示例"><a href="#Redis-Java列表示例" class="headerlink" title="Redis Java列表示例"></a>Redis Java列表示例</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">import</span> redis.clients.jedis.Jedis; </div><div class="line"></div><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RedisListJava</span> </span>&#123; </div><div class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123; </div><div class="line">      <span class="comment">//Connecting to Redis server on localhost </span></div><div class="line">      Jedis jedis = <span class="keyword">new</span> Jedis(<span class="string">"localhost"</span>); </div><div class="line">      System.out.println(<span class="string">"Connection to server sucessfully"</span>); </div><div class="line"></div><div class="line">      <span class="comment">//store data in redis list </span></div><div class="line">      jedis.lpush(<span class="string">"tutorial-list"</span>, <span class="string">"Redis"</span>); </div><div class="line">      jedis.lpush(<span class="string">"tutorial-list"</span>, <span class="string">"Mongodb"</span>); </div><div class="line">      jedis.lpush(<span class="string">"tutorial-list"</span>, <span class="string">"Mysql"</span>); </div><div class="line">      <span class="comment">// Get the stored data and print it </span></div><div class="line">      List&lt;String&gt; list = jedis.lrange(<span class="string">"tutorial-list"</span>, <span class="number">0</span> ,<span class="number">5</span>); </div><div class="line"></div><div class="line">      <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>; i&lt;list.size(); i++) &#123; </div><div class="line">         System.out.println(<span class="string">"Stored string in redis:: "</span>+list.get(i)); </div><div class="line">      &#125; </div><div class="line">   &#125; </div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;执行上面代码，将生成以下结果 -</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">$javac RedisListJava.java </div><div class="line">$java RedisListJava </div><div class="line">Connection to server sucessfully </div><div class="line">Stored string in redis:: Redis </div><div class="line">Stored string in redis:: Mongodb </div><div class="line">Stored string in redis:: Mysql</div></pre></td></tr></table></figure>
<h3 id="Redis-Java键示例"><a href="#Redis-Java键示例" class="headerlink" title="Redis Java键示例"></a>Redis Java键示例</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">import</span> redis.clients.jedis.Jedis; </div><div class="line"></div><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RedisKeyJava</span> </span>&#123; </div><div class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123; </div><div class="line">      <span class="comment">//Connecting to Redis server on localhost </span></div><div class="line">      Jedis jedis = <span class="keyword">new</span> Jedis(<span class="string">"localhost"</span>); </div><div class="line">      System.out.println(<span class="string">"Connection to server sucessfully"</span>); </div><div class="line">      <span class="comment">//store data in redis list </span></div><div class="line">      <span class="comment">// Get the stored data and print it </span></div><div class="line">      List&lt;String&gt; list = jedis.keys(<span class="string">"*"</span>); </div><div class="line"></div><div class="line">      <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>; i&lt;list.size(); i++) &#123; </div><div class="line">         System.out.println(<span class="string">"List of stored keys:: "</span>+list.get(i)); </div><div class="line">      &#125; </div><div class="line">   &#125; </div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;执行上面代码，将生成以下结果</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">$javac RedisKeyJava.java </div><div class="line">$java RedisKeyJava </div><div class="line">Connection to server sucessfully </div><div class="line">List of stored keys:: tutorial-name </div><div class="line">List of stored keys:: tutorial-list</div></pre></td></tr></table></figure>
<h2 id="19-PHP连接Redis"><a href="#19-PHP连接Redis" class="headerlink" title="19. PHP连接Redis"></a>19. PHP连接Redis</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在php程序中使用Redis之前，需要确保在机器上安装了Redis的PHP驱动程序和PHP环境。可以先在将PHP电脑上并配置好环境。</p>
<h2 id="安装-1"><a href="#安装-1" class="headerlink" title="安装"></a>安装</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;现在，让我们看看如何设置Redis PHP驱动程序。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;从github库下载phpredis=&gt; <a href="http://github.com/nicolasff/phpredis。" target="_blank" rel="external">http://github.com/nicolasff/phpredis。</a> 当下载它之后，提取文件到phpredis目录。在Ubuntu上，安装以下扩展。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">cd</span> phpredis </div><div class="line">sudo phpize </div><div class="line">sudo ./configure </div><div class="line">sudo make </div><div class="line">sudo make install</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;现在，将“modules”文件夹的内容复制并粘贴到PHP扩展目录中，并在php.ini中添加以下行。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">extension = redis.so</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;现在，Redis PHP安装完成！</p>
<h3 id="使用连接到Redis服务器"><a href="#使用连接到Redis服务器" class="headerlink" title="使用连接到Redis服务器"></a>使用连接到Redis服务器</h3><figure class="highlight php"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="meta">&lt;?php</span> </div><div class="line">   <span class="comment">//Connecting to Redis server on localhost </span></div><div class="line">   $redis = <span class="keyword">new</span> Redis(); </div><div class="line">   $redis-&gt;connect(<span class="string">'127.0.0.1'</span>, <span class="number">6379</span>); </div><div class="line">   <span class="keyword">echo</span> <span class="string">"Connection to server sucessfully"</span>; </div><div class="line">   <span class="comment">//check whether server is running or not </span></div><div class="line">   <span class="keyword">echo</span> <span class="string">"Server is running: "</span>.$redis-&gt;ping(); </div><div class="line"><span class="meta">?&gt;</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;当程序执行时，将产生以下结果。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">Connection to server sucessfully </div><div class="line">Server is running: PONG</div></pre></td></tr></table></figure>
<h3 id="Redis-PHP字符串示例"><a href="#Redis-PHP字符串示例" class="headerlink" title="Redis PHP字符串示例"></a>Redis PHP字符串示例</h3><figure class="highlight php"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="meta">&lt;?php</span> </div><div class="line">   <span class="comment">//Connecting to Redis server on localhost </span></div><div class="line">   $redis = <span class="keyword">new</span> Redis(); </div><div class="line">   $redis-&gt;connect(<span class="string">'127.0.0.1'</span>, <span class="number">6379</span>); </div><div class="line">   <span class="keyword">echo</span> <span class="string">"Connection to server sucessfully"</span>; </div><div class="line">   <span class="comment">//set the data in redis string </span></div><div class="line">   $redis-&gt;set(<span class="string">"tutorial-name"</span>, <span class="string">"Redis tutorial"</span>); </div><div class="line">   <span class="comment">// Get the stored data and print it </span></div><div class="line">   <span class="keyword">echo</span> <span class="string">"Stored string in redis:: "</span> .$redis→get(<span class="string">"tutorial-name"</span>); </div><div class="line"><span class="meta">?&gt;</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;执行上面代码，将生成以下结果</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">Connection to server sucessfully </div><div class="line">Stored string in redis:: Redis tutorial</div></pre></td></tr></table></figure>
<h3 id="Redis-php列表示例"><a href="#Redis-php列表示例" class="headerlink" title="Redis php列表示例"></a>Redis php列表示例</h3><figure class="highlight php"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line"><span class="meta">&lt;?php</span> </div><div class="line">   <span class="comment">//Connecting to Redis server on localhost </span></div><div class="line">   $redis = <span class="keyword">new</span> Redis(); </div><div class="line">   $redis-&gt;connect(<span class="string">'127.0.0.1'</span>, <span class="number">6379</span>); </div><div class="line">   <span class="keyword">echo</span> <span class="string">"Connection to server sucessfully"</span>; </div><div class="line">   <span class="comment">//store data in redis list </span></div><div class="line">   $redis-&gt;lpush(<span class="string">"tutorial-list"</span>, <span class="string">"Redis"</span>); </div><div class="line">   $redis-&gt;lpush(<span class="string">"tutorial-list"</span>, <span class="string">"Mongodb"</span>); </div><div class="line">   $redis-&gt;lpush(<span class="string">"tutorial-list"</span>, <span class="string">"Mysql"</span>);  </div><div class="line"></div><div class="line">   <span class="comment">// Get the stored data and print it </span></div><div class="line">   $arList = $redis-&gt;lrange(<span class="string">"tutorial-list"</span>, <span class="number">0</span> ,<span class="number">5</span>); </div><div class="line">   <span class="keyword">echo</span> <span class="string">"Stored string in redis:: "</span>; </div><div class="line">   print_r($arList); </div><div class="line"><span class="meta">?&gt;</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;执行上面代码，将生成以下结果</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">Connection to server sucessfully </div><div class="line">Stored string in redis:: </div><div class="line">Redis </div><div class="line">Mongodb </div><div class="line">Mysql</div></pre></td></tr></table></figure>
<h3 id="Redis-php键示例"><a href="#Redis-php键示例" class="headerlink" title="Redis php键示例"></a>Redis php键示例</h3><figure class="highlight php"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="meta">&lt;?php</span> </div><div class="line">   <span class="comment">//Connecting to Redis server on localhost </span></div><div class="line">   $redis = <span class="keyword">new</span> Redis(); </div><div class="line">   $redis-&gt;connect(<span class="string">'127.0.0.1'</span>, <span class="number">6379</span>); </div><div class="line">   <span class="keyword">echo</span> <span class="string">"Connection to server sucessfully"</span>; </div><div class="line">   <span class="comment">// Get the stored keys and print it </span></div><div class="line">   $arList = $redis-&gt;keys(<span class="string">"*"</span>); </div><div class="line">   <span class="keyword">echo</span> <span class="string">"Stored keys in redis:: "</span> </div><div class="line">   print_r($arList); </div><div class="line"><span class="meta">?&gt;</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;执行上面代码，将生成以下结果</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">Connection to server sucessfully </div><div class="line">Stored string in redis:: </div><div class="line">tutorial-name </div><div class="line">tutorial-<span class="keyword">list</span></div></pre></td></tr></table></figure>
<h2 id="20-C-连接Redis"><a href="#20-C-连接Redis" class="headerlink" title="20. C#连接Redis"></a>20. C#连接Redis</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;前面我们已经准备成功开启Redis服务，其端口号为6379，接下来我们就看看如何使用C#语言来操作Redis。就如MongoDB一样，要操作Redis服务，自然就需要下载C#的客户端，这里通过Nuget下载了“ServiceStack.Redis”客户端，引入成功之后，就可以使用C#来对Redis服务进行操作了。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;由于Redis一般是用来作为缓存的，也就是一般我们把一些不经常改变的数据通过Redis缓存起来，之后用户的请求就不需要再访问数据库，而可以直接从Redis缓存中直接获取，这样就可以减轻数据库服务器的压力以及加快响应速度。既然是用来做缓存的，也就是通过指定key值来把对应Value保存起来，之后再根据key值来获得之前缓存的值。具体的操作代码如下所示，这里就不过多介绍了。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;请参考以下代码</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div><div class="line">92</div><div class="line">93</div><div class="line">94</div><div class="line">95</div><div class="line">96</div><div class="line">97</div><div class="line">98</div><div class="line">99</div><div class="line">100</div><div class="line">101</div><div class="line">102</div><div class="line">103</div><div class="line">104</div><div class="line">105</div><div class="line">106</div><div class="line">107</div><div class="line">108</div><div class="line">109</div><div class="line">110</div><div class="line">111</div><div class="line">112</div><div class="line">113</div><div class="line">114</div><div class="line">115</div><div class="line">116</div><div class="line">117</div><div class="line">118</div><div class="line">119</div><div class="line">120</div><div class="line">121</div><div class="line">122</div><div class="line">123</div><div class="line">124</div><div class="line">125</div><div class="line">126</div><div class="line">127</div><div class="line">128</div><div class="line">129</div><div class="line">130</div><div class="line">131</div><div class="line">132</div><div class="line">133</div><div class="line">134</div><div class="line">135</div><div class="line">136</div><div class="line">137</div><div class="line">138</div><div class="line">139</div><div class="line">140</div><div class="line">141</div><div class="line">142</div><div class="line">143</div><div class="line">144</div><div class="line">145</div><div class="line">146</div><div class="line">147</div><div class="line">148</div><div class="line">149</div><div class="line">150</div><div class="line">151</div><div class="line">152</div><div class="line">153</div><div class="line">154</div><div class="line">155</div><div class="line">156</div><div class="line">157</div><div class="line">158</div><div class="line">159</div><div class="line">160</div><div class="line">161</div><div class="line">162</div><div class="line">163</div><div class="line">164</div><div class="line">165</div><div class="line">166</div><div class="line">167</div><div class="line">168</div><div class="line">169</div><div class="line">170</div><div class="line">171</div><div class="line">172</div><div class="line">173</div><div class="line">174</div><div class="line">175</div><div class="line">176</div><div class="line">177</div><div class="line">178</div><div class="line">179</div><div class="line">180</div><div class="line">181</div><div class="line">182</div></pre></td><td class="code"><pre><div class="line">class Program</div><div class="line">    &#123;</div><div class="line">        static void Main(string[] args)</div><div class="line">        &#123;</div><div class="line">            //在Redis中存储常用的5种数据类型：String,Hash,List,SetSorted set</div><div class="line">            var client = new RedisClient(&quot;127.0.0.1&quot;, 6379);</div><div class="line">            //AddString(client);</div><div class="line">            //AddHash(client);</div><div class="line">            //AddList(client);</div><div class="line">            //AddSet(client);</div><div class="line">            AddSetSorted(client);</div><div class="line"></div><div class="line">            Console.ReadLine();</div><div class="line">        &#125;</div><div class="line"></div><div class="line">        private static void AddString(RedisClient client)</div><div class="line">        &#123;</div><div class="line">            var timeOut = new TimeSpan(0,0,0,30);</div><div class="line">            client.Add(&quot;Test&quot;, &quot;Learninghard&quot;, timeOut);</div><div class="line">            while (true)</div><div class="line">            &#123;</div><div class="line">                if (client.ContainsKey(&quot;Test&quot;))</div><div class="line">                &#123;</div><div class="line">                    Console.WriteLine(&quot;String Key: Test -Value: &#123;0&#125;, 当前时间: &#123;1&#125;&quot;, client.Get&lt;string&gt;(&quot;Test&quot;), DateTime.Now);</div><div class="line">                    Thread.Sleep(10000);</div><div class="line">                &#125;</div><div class="line">                else</div><div class="line">                &#123;</div><div class="line">                    Console.WriteLine(&quot;Value 已经过期了，当前时间：&#123;0&#125;&quot;, DateTime.Now);</div><div class="line">                    break;</div><div class="line">                &#125;</div><div class="line">            &#125;</div><div class="line"></div><div class="line">            var person = new Person() &#123;Name = &quot;Learninghard&quot;, Age = 26&#125;;</div><div class="line">            client.Add(&quot;lh&quot;, person);</div><div class="line">            var cachePerson = client.Get&lt;Person&gt;(&quot;lh&quot;);</div><div class="line">            Console.WriteLine(&quot;Person&apos;s Name is : &#123;0&#125;, Age: &#123;1&#125;&quot;, cachePerson.Name, cachePerson.Age);</div><div class="line">        &#125;</div><div class="line"></div><div class="line">        private static void AddHash(RedisClient client)</div><div class="line">        &#123;</div><div class="line">            if (client == null) throw new ArgumentNullException(&quot;client&quot;);</div><div class="line"></div><div class="line">            client.SetEntryInHash(&quot;HashId&quot;, &quot;Name&quot;, &quot;Learninghard&quot;);</div><div class="line">            client.SetEntryInHash(&quot;HashId&quot;, &quot;Age&quot;, &quot;26&quot;);</div><div class="line">            client.SetEntryInHash(&quot;HashId&quot;, &quot;Sex&quot;, &quot;男&quot;);</div><div class="line"></div><div class="line">            var hashKeys = client.GetHashKeys(&quot;HashId&quot;);</div><div class="line">            foreach (var key in hashKeys)</div><div class="line">            &#123;</div><div class="line">                Console.WriteLine(&quot;HashId--Key:&#123;0&#125;&quot;, key);</div><div class="line">            &#125;</div><div class="line"></div><div class="line">            var haskValues = client.GetHashValues(&quot;HashId&quot;);</div><div class="line">            foreach (var value in haskValues)</div><div class="line">            &#123;</div><div class="line">                Console.WriteLine(&quot;HashId--Value:&#123;0&#125;&quot;, value);</div><div class="line">            &#125;</div><div class="line"></div><div class="line">            var allKeys = client.GetAllKeys(); //获取所有的key。</div><div class="line">            foreach (var key in allKeys)</div><div class="line">            &#123;</div><div class="line">                Console.WriteLine(&quot;AllKey--Key:&#123;0&#125;&quot;, key);</div><div class="line">            &#125;</div><div class="line">        &#125;</div><div class="line"></div><div class="line">        private static void AddList(RedisClient client)</div><div class="line">        &#123;</div><div class="line">            if (client == null) throw new ArgumentNullException(&quot;client&quot;);</div><div class="line"></div><div class="line">            client.EnqueueItemOnList(&quot;QueueListId&quot;, &quot;1.Learnghard&quot;);  //入队</div><div class="line">            client.EnqueueItemOnList(&quot;QueueListId&quot;, &quot;2.张三&quot;);</div><div class="line">            client.EnqueueItemOnList(&quot;QueueListId&quot;, &quot;3.李四&quot;);</div><div class="line">            client.EnqueueItemOnList(&quot;QueueListId&quot;, &quot;4.王五&quot;);</div><div class="line">            var queueCount = client.GetListCount(&quot;QueueListId&quot;);</div><div class="line"></div><div class="line">            for (var i = 0; i &lt; queueCount; i++)</div><div class="line">            &#123;</div><div class="line">                Console.WriteLine(&quot;QueueListId出队值：&#123;0&#125;&quot;, client.DequeueItemFromList(&quot;QueueListId&quot;));   //出队(队列先进先出)</div><div class="line">            &#125;</div><div class="line"></div><div class="line">            client.PushItemToList(&quot;StackListId&quot;, &quot;1.Learninghard&quot;);  //入栈</div><div class="line">            client.PushItemToList(&quot;StackListId&quot;, &quot;2.张三&quot;);</div><div class="line">            client.PushItemToList(&quot;StackListId&quot;, &quot;3.李四&quot;);</div><div class="line">            client.PushItemToList(&quot;StackListId&quot;, &quot;4.王五&quot;);</div><div class="line"></div><div class="line">            var stackCount = client.GetListCount(&quot;StackListId&quot;);</div><div class="line">            for (var i = 0; i &lt; stackCount; i++)</div><div class="line">            &#123;</div><div class="line">                Console.WriteLine(&quot;StackListId出栈值：&#123;0&#125;&quot;, client.PopItemFromList(&quot;StackListId&quot;));   //出栈(栈先进后出)</div><div class="line">            &#125;</div><div class="line">        &#125;</div><div class="line"></div><div class="line">        //它是string类型的无序集合。set是通过hash table实现的，添加，删除和查找,对集合我们可以取并集，交集，差集</div><div class="line">        private static void AddSet(RedisClient client)</div><div class="line">        &#123;</div><div class="line">            if (client == null) throw new ArgumentNullException(&quot;client&quot;);</div><div class="line"></div><div class="line">            client.AddItemToSet(&quot;Set1001&quot;, &quot;A&quot;);</div><div class="line">            client.AddItemToSet(&quot;Set1001&quot;, &quot;B&quot;);</div><div class="line">            client.AddItemToSet(&quot;Set1001&quot;, &quot;C&quot;);</div><div class="line">            client.AddItemToSet(&quot;Set1001&quot;, &quot;D&quot;);</div><div class="line">            var hastset1 = client.GetAllItemsFromSet(&quot;Set1001&quot;);</div><div class="line">            foreach (var item in hastset1)</div><div class="line">            &#123;</div><div class="line">                Console.WriteLine(&quot;Set无序集合Value:&#123;0&#125;&quot;, item); //出来的结果是无须的</div><div class="line">            &#125;</div><div class="line"></div><div class="line">            client.AddItemToSet(&quot;Set1002&quot;, &quot;K&quot;);</div><div class="line">            client.AddItemToSet(&quot;Set1002&quot;, &quot;C&quot;);</div><div class="line">            client.AddItemToSet(&quot;Set1002&quot;, &quot;A&quot;);</div><div class="line">            client.AddItemToSet(&quot;Set1002&quot;, &quot;J&quot;);</div><div class="line">            var hastset2 = client.GetAllItemsFromSet(&quot;Set1002&quot;);</div><div class="line">            foreach (var item in hastset2)</div><div class="line">            &#123;</div><div class="line">                Console.WriteLine(&quot;Set无序集合ValueB:&#123;0&#125;&quot;, item); //出来的结果是无须的</div><div class="line">            &#125;</div><div class="line"></div><div class="line">            var hashUnion = client.GetUnionFromSets(new string[] &#123; &quot;Set1001&quot;, &quot;Set1002&quot; &#125;);</div><div class="line">            foreach (var item in hashUnion)</div><div class="line">            &#123;</div><div class="line">                Console.WriteLine(&quot;求Set1001和Set1002的并集:&#123;0&#125;&quot;, item); //并集</div><div class="line">            &#125;</div><div class="line"></div><div class="line">            var hashG = client.GetIntersectFromSets(new string[] &#123; &quot;Set1001&quot;, &quot;Set1002&quot; &#125;);</div><div class="line">            foreach (var item in hashG)</div><div class="line">            &#123;</div><div class="line">                Console.WriteLine(&quot;求Set1001和Set1002的交集:&#123;0&#125;&quot;, item);  //交集</div><div class="line">            &#125;</div><div class="line"></div><div class="line">            var hashD = client.GetDifferencesFromSet(&quot;Set1001&quot;, new string[] &#123; &quot;Set1002&quot; &#125;);  //[返回存在于第一个集合，但是不存在于其他集合的数据。差集]</div><div class="line">            foreach (var item in hashD)</div><div class="line">            &#123;</div><div class="line">                Console.WriteLine(&quot;求Set1001和Set1002的差集:&#123;0&#125;&quot;, item);  //差集</div><div class="line">            &#125;</div><div class="line"></div><div class="line">        &#125;</div><div class="line"></div><div class="line">        /*</div><div class="line">        sorted set 是set的一个升级版本，它在set的基础上增加了一个顺序的属性，这一属性在添加修改.元素的时候可以指定，</div><div class="line">        * 每次指定后，zset(表示有序集合)会自动重新按新的值调整顺序。可以理解为有列的表，一列存 value,一列存顺序。操作中key理解为zset的名字.</div><div class="line">        */</div><div class="line">        private static void AddSetSorted(RedisClient client)</div><div class="line">        &#123;</div><div class="line">            if (client == null) throw new ArgumentNullException(&quot;client&quot;);</div><div class="line"></div><div class="line">            client.AddItemToSortedSet(&quot;SetSorted1001&quot;, &quot;A&quot;);</div><div class="line">            client.AddItemToSortedSet(&quot;SetSorted1001&quot;, &quot;B&quot;);</div><div class="line">            client.AddItemToSortedSet(&quot;SetSorted1001&quot;, &quot;C&quot;);</div><div class="line">            var listSetSorted = client.GetAllItemsFromSortedSet(&quot;SetSorted1001&quot;);</div><div class="line">            foreach (var item in listSetSorted)</div><div class="line">            &#123;</div><div class="line">                Console.WriteLine(&quot;SetSorted有序集合&#123;0&#125;&quot;, item);</div><div class="line">            &#125;</div><div class="line"></div><div class="line">            client.AddItemToSortedSet(&quot;SetSorted1002&quot;, &quot;A&quot;, 400);</div><div class="line">            client.AddItemToSortedSet(&quot;SetSorted1002&quot;, &quot;D&quot;, 200);</div><div class="line">            client.AddItemToSortedSet(&quot;SetSorted1002&quot;, &quot;B&quot;, 300);</div><div class="line"></div><div class="line">            // 升序获取第一个值:&quot;D&quot;</div><div class="line">            var list = client.GetRangeFromSortedSet(&quot;SetSorted1002&quot;, 0, 0);</div><div class="line"></div><div class="line">            foreach (var item in list)</div><div class="line">            &#123;</div><div class="line">                Console.WriteLine(item);</div><div class="line">            &#125;</div><div class="line"></div><div class="line">            //降序获取第一个值:&quot;A&quot;</div><div class="line">            list = client.GetRangeFromSortedSetDesc(&quot;SetSorted1002&quot;, 0, 0);</div><div class="line"></div><div class="line">            foreach (var item in list)</div><div class="line">            &#123;</div><div class="line">                Console.WriteLine(item);</div><div class="line">            &#125;</div><div class="line">        &#125;</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    class Person</div><div class="line">    &#123;</div><div class="line">        public string Name &#123; get; set; &#125;</div><div class="line">        public int Age &#123; get; set; &#125;</div><div class="line">    &#125;</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;如何要想查看自己操作是否成功，也可以像MongoDB那样下载一个客户端工具，这里推荐一款Redis Desktop Manager。这个工具就相当于SQL Server的客户端工具一样。通过这款工具可以查看Redis服务器中保存的数据和对应格式。其使用也非常简单，只需要添加一个Redis服务连接即可。该工具的下载地址为：<a href="http://pan.baidu.com/s/1sjp55Ul" target="_blank" rel="external">http://pan.baidu.com/s/1sjp55Ul</a></p>

	

	

</article>




	<article>
	
		<h1><a href="/2017/10/12/Redis/1. Redis下载安装/">Redis下载安装</a></h1>
	
	<div class="article__infos">
		<span class="article__date">2017-10-12</span><br />
		
		
			<span class="article__tags">
			  	<a class="article__tag-link" href="/tags/Redis/">Redis</a>
			</span>
		
	</div>

	

	
		<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;redis是一个key-value存储系统，<a href="http://redis.io" target="_blank" rel="external">官方站点</a></p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;和memcached类似，但支持数据持久化</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;支持更多value类型，除了和string外，还支持hash、lists（链表）、sets（集合）和sorted sets（有序集合）几种数据类型</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;redis使用了两种文件格式：全量数据（RDB）和增量请求（aof)。全量数据格式是 把内存中的数据写入磁盘，便于下次读取文件进行加载。增量请求文件则是把内存中的 数据序列化为操作请求，用于读取文件进行replay得到数据redis的存储分为内存存储、    磁盘存储和log文件三部分</p>
<h2 id="1-redis-安装"><a href="#1-redis-安装" class="headerlink" title="1.redis 安装"></a>1.redis 安装</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<a href="http://redis.io/download" target="_blank" rel="external">官网下载地址</a></p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;下载 redis</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">[root@redis ~]<span class="comment"># wget http://download.redis.io/releases/redis-3.2.8.tar.gz</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;解压</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">[root@redis ~]<span class="comment"># tar zxvf redis-3.2.8.tar.gz</span></div></pre></td></tr></table></figure>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">[root@redis ~]<span class="comment"># cd redis-3.2.8</span></div></pre></td></tr></table></figure>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">[root@redis redis-3.2.8]<span class="comment"># yum install -y gcc epel-release</span></div></pre></td></tr></table></figure>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">[root@redis redis-3.2.8]<span class="comment"># yum install -y jemalloc-devel</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;编译</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">[root@redis redis-3.2.8]<span class="comment"># make</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;如果出错，运行如下命令：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">[root@redis redis-3.2.8]<span class="comment"># cd deps/</span></div><div class="line">[root@redis deps]<span class="comment"># make hiredis lua jemalloc linenoise/</span></div></pre></td></tr></table></figure>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">[root@redis deps]<span class="comment"># cd ..</span></div><div class="line">[root@redis redis-3.2.8]<span class="comment"># make</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;安装</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">[root@redis redis-3.2.8]<span class="comment"># make PREFIX=/usr/local/redis install</span></div></pre></td></tr></table></figure>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">[root@redis redis-3.2.8]<span class="comment"># mkdir /usr/local/redis/etc</span></div></pre></td></tr></table></figure>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">[root@redis ~]<span class="comment"># wget http://www.apelearn.com/study_v2/.redis_conf -O /usr/local/redis/etc/redis.conf 2&gt;/dev/null</span></div></pre></td></tr></table></figure>
<h3 id="redis-启动脚本"><a href="#redis-启动脚本" class="headerlink" title="redis 启动脚本"></a>redis 启动脚本</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">[root@redis ~]<span class="comment"># wget http://www.apelearn.com/study_v2/.redis_init -O /etc/init.d/redis 2&gt;/dev/null</span></div></pre></td></tr></table></figure>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">[root@redis ~]<span class="comment"># useradd -s /sbin/nologin redis</span></div><div class="line">[root@redis ~]<span class="comment"># mkdir /usr/local/redis/var</span></div><div class="line">[root@redis ~]<span class="comment"># chmod 777 /usr/local/redis/var</span></div><div class="line">[root@redis ~]<span class="comment"># chmod 755 /etc/init.d/redis</span></div><div class="line">[root@redis ~]<span class="comment"># chkconfig --add redis</span></div><div class="line">[root@redis ~]<span class="comment"># chkconfig redis on</span></div><div class="line">[root@redis ~]<span class="comment"># service redis start</span></div><div class="line">启动 ：                              [确定]</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<a href="https://hcldirgit.github.io/2017/08/25/Redis/24.%20redis%20%E9%85%8D%E7%BD%AE/" target="_blank" rel="external">redis 配置</a></p>
<h2 id="2-redis-数据结构"><a href="#2-redis-数据结构" class="headerlink" title="2.redis 数据结构"></a>2.redis 数据结构</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<a href="https://hcldirgit.github.io/2017/08/25/Redis/25.%20Redis%20%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B/" target="_blank" rel="external">Redis 数据类型</a></p>
<h3 id="redis-数据类型-string"><a href="#redis-数据类型-string" class="headerlink" title="redis 数据类型 - string"></a>redis 数据类型 - string</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;string是最简单的类型，你可以理解成与Memcached一样的类型，一个key对应一个value，其上支持的操作与Memcached的操作类似，它的功能更丰富。设置可以存二进制的对象。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;示例：</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;首先</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">[root@redis ~]<span class="comment"># alias redis-cli='/usr/local/redis/bin/redis-cli'</span></div><div class="line">[root@redis ~]<span class="comment"># vim .bashrc</span></div></pre></td></tr></table></figure>
<p><figure class="figure"><img src="https://github.com/hcldirgit/image/blob/master/redis%E4%B8%8B%E8%BD%BD%E5%AE%89%E8%A3%85/01.png?raw=true" alt="01"><figcaption class="figure__caption">01</figcaption></figure></p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;这样就可以直接使用 redis-cli 命令，或者编辑 profile </p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">[root@redis ~]<span class="comment"># redis-cli set mykey "yanyi.com"</span></div></pre></td></tr></table></figure>
<p><figure class="figure"><img src="https://github.com/hcldirgit/image/blob/master/redis%E4%B8%8B%E8%BD%BD%E5%AE%89%E8%A3%85/02.png?raw=true" alt="02"><figcaption class="figure__caption">02</figcaption></figure></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">[root@redis ~]<span class="comment"># redis-cli get mykey</span></div></pre></td></tr></table></figure>
<p><figure class="figure"><img src="https://github.com/hcldirgit/image/blob/master/redis%E4%B8%8B%E8%BD%BD%E5%AE%89%E8%A3%85/03.png?raw=true" alt="03"><figcaption class="figure__caption">03</figcaption></figure></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">[root@redis ~]<span class="comment"># redis-cli</span></div></pre></td></tr></table></figure>
<p><figure class="figure"><img src="https://github.com/hcldirgit/image/blob/master/redis%E4%B8%8B%E8%BD%BD%E5%AE%89%E8%A3%85/04.png?raw=true" alt="04"><figcaption class="figure__caption">04</figcaption></figure></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">127.0.0.1:6379&gt; mset key1 1 key2 a key3 c </div><div class="line">OK</div><div class="line">127.0.0.1:6379&gt; mget key1 key2 key3</div><div class="line">1) <span class="string">"1"</span></div><div class="line">2) <span class="string">"a"</span></div><div class="line">3) <span class="string">"c"</span></div></pre></td></tr></table></figure>
<p><figure class="figure"><img src="https://github.com/hcldirgit/image/blob/master/redis%E4%B8%8B%E8%BD%BD%E5%AE%89%E8%A3%85/05.png?raw=true" alt="05"><figcaption class="figure__caption">05</figcaption></figure></p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<a href="https://hcldirgit.github.io/2017/08/24/Redis/18.%20Redis%20%E5%AD%97%E7%AC%A6%E4%B8%B2(String" target="_blank" rel="external">Redis 字符串(String)</a>/)</p>
<h3 id="redis-数据类型-list"><a href="#redis-数据类型-list" class="headerlink" title="redis 数据类型 - list"></a>redis 数据类型 - list</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;list是一个链表结构，主要功能是push、pop、获取一个范围的所有值等等。操作中key理解为链表的名字。使用 List 结构，我们可以轻松地实现最新消息排行等功能（比如新浪微博的 TimeLine ）。list 的另一个应用就是消息队列，可以利用 list 的 push操作，将任务存在 list 中，然后工作线程再用pop操作将任务取出进行执行。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;示例：</p>
<p><figure class="figure"><img src="https://github.com/hcldirgit/image/blob/master/redis%E4%B8%8B%E8%BD%BD%E5%AE%89%E8%A3%85/06.png?raw=true" alt="06"><figcaption class="figure__caption">06</figcaption></figure></p>
<p><figure class="figure"><img src="https://github.com/hcldirgit/image/blob/master/redis%E4%B8%8B%E8%BD%BD%E5%AE%89%E8%A3%85/07.png?raw=true" alt="07"><figcaption class="figure__caption">07</figcaption></figure></p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<a href="https://hcldirgit.github.io/2017/08/24/Redis/20.%20Redis%20%E5%88%97%E8%A1%A8(List" target="_blank" rel="external">Redis 列表(List)</a>/)</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;注： <a href="https://hcldirgit.github.io/2017/08/24/Redis/7.%20Redis%20list%20%E4%B9%8B%E5%A2%9E%E5%88%A0%E6%94%B9%E6%9F%A5/" target="_blank" rel="external">Redis list 之增删改查</a></p>
<h3 id="redis-数据类型-set"><a href="#redis-数据类型-set" class="headerlink" title="redis 数据类型 - set"></a>redis 数据类型 - set</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;set是集合，和我们数学中的集合概念相似，对集合的操作有添加删除元素，有对多个集合求交并差等操作。操作中key理解为集合的名字。比如在微博应用中，可以将一个用户所有的关注人存在一个集合中，将其所有粉丝存在一个集合。因为 Redis 非常人性化的为集合提供了求交集、并集、差集等操作，那么就可以非常方便的实现如共同关注、共同喜好、二度好友等功能，对上面的所有集合操作，你还可以使用不同的命令选择将结果返回给客户端还是存集到一个新的集合中。QQ有一个社交功能叫做“好友标签”，大家可以给你的好友贴标签，比如“大美女”、“土豪”、“欧巴”等等，这时就可以使用redis的集合来实现，把每一个用户的标签都存储在一个集合之中。</p>
<p><figure class="figure"><img src="https://github.com/hcldirgit/image/blob/master/redis%E4%B8%8B%E8%BD%BD%E5%AE%89%E8%A3%85/08.png?raw=true" alt="08"><figcaption class="figure__caption">08</figcaption></figure></p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<a href="https://hcldirgit.github.io/2017/08/24/Redis/21.%20Redis%20%E9%9B%86%E5%90%88(Set" target="_blank" rel="external">Redis 集合(Set)</a>/)</p>
<h3 id="redis-数据类型-sort-set"><a href="#redis-数据类型-sort-set" class="headerlink" title="redis 数据类型 - sort set"></a>redis 数据类型 - sort set</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;sorted set是有序集合，它比set多了一个权重参数score，使得集合中的元素能够按 score 进行有序排列，比如一个存储全班同学成绩的 Sorted Sets，其集合 value 可以是同学的学号，而 score 就可以是其考试得分，这样在数据插入集合的时候，就已经进行了天然的排序。</p>
<p><figure class="figure"><img src="https://github.com/hcldirgit/image/blob/master/redis%E4%B8%8B%E8%BD%BD%E5%AE%89%E8%A3%85/09.png?raw=true" alt="09"><figcaption class="figure__caption">09</figcaption></figure></p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;倒序 </p>
<p><figure class="figure"><img src="https://github.com/hcldirgit/image/blob/master/redis%E4%B8%8B%E8%BD%BD%E5%AE%89%E8%A3%85/10.png?raw=true" alt="10"><figcaption class="figure__caption">10</figcaption></figure></p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<a href="https://hcldirgit.github.io/2017/08/24/Redis/22.%20Redis%20%E6%9C%89%E5%BA%8F%E9%9B%86%E5%90%88(sorted%20set" target="_blank" rel="external">Redis 有序集合(sorted set)</a>/)</p>
<h3 id="redis-数据类型-hash"><a href="#redis-数据类型-hash" class="headerlink" title="redis 数据类型 - hash"></a>redis 数据类型 - hash</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在 Memcached 中，我们经常将一些结构化的信息打包成 hashmap，在客户端序列化后存储为一个字符串的值（一般是 JSON 格式），比如用户的昵称、年龄、性别、积分等。</p>
<p><figure class="figure"><img src="https://github.com/hcldirgit/image/blob/master/redis%E4%B8%8B%E8%BD%BD%E5%AE%89%E8%A3%85/11.png?raw=true" alt="11"><figcaption class="figure__caption">11</figcaption></figure></p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<a href="https://hcldirgit.github.io/2017/08/24/Redis/19.%20Redis%20%E5%93%88%E5%B8%8C(Hash" target="_blank" rel="external">Redis 哈希(Hash)</a>/)</p>
<h2 id="3-redis持久化"><a href="#3-redis持久化" class="headerlink" title="3.redis持久化"></a>3.redis持久化</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Redis提供了两种持久化的方式，分别是RDB（Redis DataBase）和AOF（Append Only File）。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;RDB，简而言之，就是在不同的时间点，将redis存储的数据生成快照并存储到磁盘等介质上。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;AOF，则是换了一个角度来实现持久化，那就是将redis执行过的所有写指令记录下来，在下次redis重新启动时，只要把这些写指令从前到后再重复执行一遍，就可以实现数据恢复了。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;其实RDB和AOF两种方式也可以同时使用，在这种情况下，如果redis重启的话，则会优先采用AOF方式来进行数据恢复，这是因为AOF方式的数据恢复完整度更高。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;如果你没有数据持久化的需求，也完全可以关闭RDB和AOF方式，这样的话，redis将变成一个纯内存数据库，就像memcache一样。</p>

	

	

</article>




	<article>
	
		<h1><a href="/2017/10/12/Python/1. Python 基础篇/1. Python 基础语法/2.3 流程控制-for 字典/Python 流程控制-for循环 字典/">Python 流程控制-for循环字典</a></h1>
	
	<div class="article__infos">
		<span class="article__date">2017-10-12</span><br />
		
		
			<span class="article__tags">
			  	<a class="article__tag-link" href="/tags/Python/">Python</a>
			</span>
		
	</div>

	

	
		<h1 id="Python-流程控制-for循环-字典"><a href="#Python-流程控制-for循环-字典" class="headerlink" title="Python 流程控制-for循环 字典"></a>Python 流程控制-for循环 字典</h1><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Python for循环不但可以遍历序列，还可以遍历字典。</p>
<h2 id="通过-for-循环遍历字典"><a href="#通过-for-循环遍历字典" class="headerlink" title="通过 for 循环遍历字典"></a>通过 for 循环遍历字典</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;先定义一个字典</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">In [<span class="number">4</span>]: dic = &#123;<span class="string">'a'</span>:<span class="number">1</span>, <span class="string">'b'</span>:<span class="number">2</span>&#125;</div><div class="line"></div><div class="line">In [<span class="number">5</span>]: dic.fromkeys(<span class="string">'abcde'</span>,<span class="number">100</span>)</div><div class="line">Out[<span class="number">5</span>]: &#123;<span class="string">'a'</span>: <span class="number">100</span>, <span class="string">'b'</span>: <span class="number">100</span>, <span class="string">'c'</span>: <span class="number">100</span>, <span class="string">'d'</span>: <span class="number">100</span>, <span class="string">'e'</span>: <span class="number">100</span>&#125;</div><div class="line"></div><div class="line">In [<span class="number">6</span>]: dic1 = dic.fromkeys(<span class="string">'abcde'</span>,<span class="number">100</span>)</div><div class="line"></div><div class="line">In [<span class="number">7</span>]: dic1</div><div class="line">Out[<span class="number">7</span>]: &#123;<span class="string">'a'</span>: <span class="number">100</span>, <span class="string">'b'</span>: <span class="number">100</span>, <span class="string">'c'</span>: <span class="number">100</span>, <span class="string">'d'</span>: <span class="number">100</span>, <span class="string">'e'</span>: <span class="number">100</span>&#125;</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;遍历字典里的 key （直接遍历字典，不加任何方法就是遍历字典的 key）</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line">In [<span class="number">8</span>]: <span class="keyword">for</span> k <span class="keyword">in</span> dic:</div><div class="line">   ...:     <span class="keyword">print</span> k</div><div class="line">   ...:     </div><div class="line">a</div><div class="line">b</div><div class="line"></div><div class="line">In [<span class="number">9</span>]: <span class="keyword">for</span> k <span class="keyword">in</span> dic1:</div><div class="line">   ...:     <span class="keyword">print</span> k</div><div class="line">   ...:     </div><div class="line">a</div><div class="line">c</div><div class="line">b</div><div class="line">e</div><div class="line">d</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;取字典里的值（要遍历 value 就要加上 dic1[k] 索引下标来取）</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">In [<span class="number">10</span>]: <span class="keyword">for</span> k <span class="keyword">in</span> dic1:</div><div class="line">    ...:     <span class="keyword">print</span> k,dic1[k]</div><div class="line">    ...:     </div><div class="line">a <span class="number">100</span></div><div class="line">c <span class="number">100</span></div><div class="line">b <span class="number">100</span></div><div class="line">e <span class="number">100</span></div><div class="line">d <span class="number">100</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;格式化的输出</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">In [<span class="number">11</span>]: <span class="keyword">for</span> k <span class="keyword">in</span> dic1:</div><div class="line">    ...:     <span class="keyword">print</span> <span class="string">"%s --&gt; %s"</span> % (k,dic1[k])</div><div class="line">    ...:     </div><div class="line">a --&gt; 100</div><div class="line">c --&gt; 100</div><div class="line">b --&gt; 100</div><div class="line">e --&gt; 100</div><div class="line">d --&gt; 100</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;如果只要占一行就在后边加逗号</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">In [<span class="number">12</span>]: <span class="keyword">for</span> k <span class="keyword">in</span> dic1:</div><div class="line">    ...:     <span class="keyword">print</span> <span class="string">"%s --&gt; %s"</span> % (k,dic1[k]),</div><div class="line">    ...:     </div><div class="line">a --&gt; 100 c --&gt; 100 b --&gt; 100 e --&gt; 100 d --&gt; 100</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;还可以把字典作为列表遍历，取到每个元素也就是元组（使用 items() 遍历，通过一个值取出来就是元组）</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">In [<span class="number">13</span>]: dic1.items()</div><div class="line">Out[<span class="number">13</span>]: [(<span class="string">'a'</span>, <span class="number">100</span>), (<span class="string">'c'</span>, <span class="number">100</span>), (<span class="string">'b'</span>, <span class="number">100</span>), (<span class="string">'e'</span>, <span class="number">100</span>), (<span class="string">'d'</span>, <span class="number">100</span>)]</div><div class="line"></div><div class="line">In [<span class="number">14</span>]: <span class="keyword">for</span> i <span class="keyword">in</span> dic1.items():<span class="keyword">print</span> i</div><div class="line">(<span class="string">'a'</span>, <span class="number">100</span>)</div><div class="line">(<span class="string">'c'</span>, <span class="number">100</span>)</div><div class="line">(<span class="string">'b'</span>, <span class="number">100</span>)</div><div class="line">(<span class="string">'e'</span>, <span class="number">100</span>)</div><div class="line">(<span class="string">'d'</span>, <span class="number">100</span>)</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;然后可以对元组进行拆分（使用 items(),通过两个值来取就可以拆分元组）</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">In [<span class="number">15</span>]: <span class="keyword">for</span> k,v <span class="keyword">in</span> dic1.items():<span class="keyword">print</span> k,v</div><div class="line">a <span class="number">100</span></div><div class="line">c <span class="number">100</span></div><div class="line">b <span class="number">100</span></div><div class="line">e <span class="number">100</span></div><div class="line">d <span class="number">100</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;也可以用 dic1.iteritems() ，只不过它返回是个对象；而 items() 是个列表。可以对这个对象进行遍历，用两个值（k和v）来接收，就可以得到两个值 key 和 value</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">In [<span class="number">16</span>]: <span class="keyword">for</span> k,v <span class="keyword">in</span> dic1.iteritems():<span class="keyword">print</span> k,v</div><div class="line">a <span class="number">100</span></div><div class="line">c <span class="number">100</span></div><div class="line">b <span class="number">100</span></div><div class="line">e <span class="number">100</span></div><div class="line">d <span class="number">100</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;以上就是通过 for 循环遍历字典的方法</p>
<h2 id="实例"><a href="#实例" class="headerlink" title="实例"></a>实例</h2><h3 id="实例1：乘法口诀表"><a href="#实例1：乘法口诀表" class="headerlink" title="实例1：乘法口诀表"></a>实例1：乘法口诀表</h3><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;两个循环</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="comment">#!/usr/bin/python</span></div><div class="line"></div><div class="line"><span class="keyword">for</span> i <span class="keyword">in</span> xrange(<span class="number">1</span>,<span class="number">10</span>):    <span class="comment">#控制行数</span></div><div class="line">    <span class="keyword">for</span> j <span class="keyword">in</span> xrange(<span class="number">1</span>,i+<span class="number">1</span>):    <span class="comment">#每列的列数不一样，用j表示，控制列数</span></div><div class="line">        <span class="keyword">print</span> <span class="string">"%s * %s = %s"</span> % (j, i j*i),    <span class="comment">#用逗号不输出换行符</span></div><div class="line">    <span class="keyword">print</span>    <span class="comment">#直接print输出换行,或者使用 print "\n"</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;输出结果</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line">[root@localhost ~]<span class="comment"># python 3.py </span></div><div class="line"><span class="number">1</span>*<span class="number">1</span>=<span class="number">1</span></div><div class="line"><span class="number">1</span>*<span class="number">2</span>=<span class="number">2</span> <span class="number">2</span>*<span class="number">2</span>=<span class="number">4</span></div><div class="line"><span class="number">1</span>*<span class="number">3</span>=<span class="number">3</span> <span class="number">2</span>*<span class="number">3</span>=<span class="number">6</span> <span class="number">3</span>*<span class="number">3</span>=<span class="number">9</span></div><div class="line"><span class="number">1</span>*<span class="number">4</span>=<span class="number">4</span> <span class="number">2</span>*<span class="number">4</span>=<span class="number">8</span> <span class="number">3</span>*<span class="number">4</span>=<span class="number">12</span> <span class="number">4</span>*<span class="number">4</span>=<span class="number">16</span></div><div class="line"><span class="number">1</span>*<span class="number">5</span>=<span class="number">5</span> <span class="number">2</span>*<span class="number">5</span>=<span class="number">10</span> <span class="number">3</span>*<span class="number">5</span>=<span class="number">15</span> <span class="number">4</span>*<span class="number">5</span>=<span class="number">20</span> <span class="number">5</span>*<span class="number">5</span>=<span class="number">25</span></div><div class="line"><span class="number">1</span>*<span class="number">6</span>=<span class="number">6</span> <span class="number">2</span>*<span class="number">6</span>=<span class="number">12</span> <span class="number">3</span>*<span class="number">6</span>=<span class="number">18</span> <span class="number">4</span>*<span class="number">6</span>=<span class="number">24</span> <span class="number">5</span>*<span class="number">6</span>=<span class="number">30</span> <span class="number">6</span>*<span class="number">6</span>=<span class="number">36</span></div><div class="line"><span class="number">1</span>*<span class="number">7</span>=<span class="number">7</span> <span class="number">2</span>*<span class="number">7</span>=<span class="number">14</span> <span class="number">3</span>*<span class="number">7</span>=<span class="number">21</span> <span class="number">4</span>*<span class="number">7</span>=<span class="number">28</span> <span class="number">5</span>*<span class="number">7</span>=<span class="number">35</span> <span class="number">6</span>*<span class="number">7</span>=<span class="number">42</span> <span class="number">7</span>*<span class="number">7</span>=<span class="number">49</span></div><div class="line"><span class="number">1</span>*<span class="number">8</span>=<span class="number">8</span> <span class="number">2</span>*<span class="number">8</span>=<span class="number">16</span> <span class="number">3</span>*<span class="number">8</span>=<span class="number">24</span> <span class="number">4</span>*<span class="number">8</span>=<span class="number">32</span> <span class="number">5</span>*<span class="number">8</span>=<span class="number">40</span> <span class="number">6</span>*<span class="number">8</span>=<span class="number">48</span> <span class="number">7</span>*<span class="number">8</span>=<span class="number">56</span> <span class="number">8</span>*<span class="number">8</span>=<span class="number">64</span></div><div class="line"><span class="number">1</span>*<span class="number">9</span>=<span class="number">9</span> <span class="number">2</span>*<span class="number">9</span>=<span class="number">18</span> <span class="number">3</span>*<span class="number">9</span>=<span class="number">27</span> <span class="number">4</span>*<span class="number">9</span>=<span class="number">36</span> <span class="number">5</span>*<span class="number">9</span>=<span class="number">45</span> <span class="number">6</span>*<span class="number">9</span>=<span class="number">54</span> <span class="number">7</span>*<span class="number">9</span>=<span class="number">63</span> <span class="number">8</span>*<span class="number">9</span>=<span class="number">72</span> <span class="number">9</span>*<span class="number">9</span>=<span class="number">81</span></div></pre></td></tr></table></figure>

	

	

</article>




	<article>
	
		<h1><a href="/2017/10/12/Python/1. Python 基础篇/1. Python 基础语法/2.2 流程控制-for 序列/14. Python 流程控制- for 循环序列/">Python 流程控制-for循环序列</a></h1>
	
	<div class="article__infos">
		<span class="article__date">2017-10-12</span><br />
		
		
			<span class="article__tags">
			  	<a class="article__tag-link" href="/tags/Python/">Python</a>
			</span>
		
	</div>

	

	
		<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;什么是循环：</p>
<ul>
<li>循环是一个结构，导致程序要重复一定的次数。</li>
<li>条件循环也是如此，当条件为假，循环结束。</li>
</ul>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Python for循环可以遍历任何序列的项目，如一个列表或者一个字符串。</p>
<h2 id="语法"><a href="#语法" class="headerlink" title="语法"></a>语法</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">for</span> iterating_var <span class="keyword">in</span> sequence:</div><div class="line">    statements(s)</div></pre></td></tr></table></figure>
<h3 id="流程图"><a href="#流程图" class="headerlink" title="流程图"></a>流程图</h3><p><figure class="figure"><img src="https://github.com/hcldirgit/image/blob/master/python%E6%B5%81%E7%A8%8B%E6%8E%A7%E5%88%B6-for%E5%BA%8F%E5%88%97/01.jpg?raw=true" alt="images"><figcaption class="figure__caption">images</figcaption></figure></p>
<h3 id="实例"><a href="#实例" class="headerlink" title="实例"></a>实例</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="comment">#!/usr/bin/python</span></div><div class="line"></div><div class="line"><span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">10</span>)：</div><div class="line">    <span class="keyword">print</span> i</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;输出结果：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="number">0</span></div><div class="line"><span class="number">1</span></div><div class="line"><span class="number">2</span></div><div class="line"><span class="number">3</span></div><div class="line"><span class="number">4</span></div><div class="line"><span class="number">5</span></div><div class="line"><span class="number">6</span></div><div class="line"><span class="number">7</span></div><div class="line"><span class="number">8</span></div><div class="line"><span class="number">9</span></div></pre></td></tr></table></figure>
<h2 id="range"><a href="#range" class="headerlink" title="range"></a>range</h2><ul>
<li>range可以快速的生成一个序列</li>
<li>range（i，j,[,步进值]）<ul>
<li>如果所创建对象为整数，可以用range</li>
<li>i为初始值，不选默认为0</li>
<li>j为终止值，但不包括在范围内</li>
<li>步进值默认为1</li>
</ul>
</li>
</ul>
<h2 id="for循环实例"><a href="#for循环实例" class="headerlink" title="for循环实例"></a>for循环实例</h2><h3 id="实例1：显示1-10，能被2整除的数"><a href="#实例1：显示1-10，能被2整除的数" class="headerlink" title="实例1：显示1-10，能被2整除的数"></a>实例1：显示1-10，能被2整除的数</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="comment">#!/usr/bin/python</span></div><div class="line"></div><div class="line"><span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">1</span>,<span class="number">11</span>):</div><div class="line">    i % <span class="number">2</span> == <span class="number">0</span>:</div><div class="line">        <span class="keyword">print</span> i</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;输出结果：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="number">2</span></div><div class="line"><span class="number">4</span></div><div class="line"><span class="number">6</span></div><div class="line"><span class="number">8</span></div><div class="line"><span class="number">10</span></div></pre></td></tr></table></figure>
<h3 id="实例2："><a href="#实例2：" class="headerlink" title="实例2："></a>实例2：</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="comment">#!/usr/bin/python</span></div><div class="line"></div><div class="line"><span class="keyword">print</span> [i <span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">1</span>,<span class="number">11</span>)]:</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;输出结果：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="number">1</span></div><div class="line"><span class="number">2</span></div><div class="line"><span class="number">3</span></div><div class="line"><span class="number">4</span></div><div class="line"><span class="number">5</span></div><div class="line"><span class="number">6</span></div><div class="line"><span class="number">7</span></div><div class="line"><span class="number">8</span></div><div class="line"><span class="number">9</span></div><div class="line"><span class="number">10</span></div></pre></td></tr></table></figure>
<h3 id="实例3"><a href="#实例3" class="headerlink" title="实例3"></a>实例3</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="comment">#!/usr/bin/python</span></div><div class="line"></div><div class="line"><span class="keyword">print</span> [i*<span class="number">2</span> <span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">1</span>,<span class="number">11</span>)]:</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;输出结果：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="number">2</span></div><div class="line"><span class="number">4</span></div><div class="line"><span class="number">6</span></div><div class="line"><span class="number">8</span></div><div class="line"><span class="number">10</span></div><div class="line"><span class="number">12</span></div><div class="line"><span class="number">14</span></div><div class="line"><span class="number">16</span></div><div class="line"><span class="number">18</span></div><div class="line"><span class="number">20</span></div></pre></td></tr></table></figure>
<h3 id="实例4"><a href="#实例4" class="headerlink" title="实例4"></a>实例4</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="comment">#!/usr/bin/python</span></div><div class="line"></div><div class="line"><span class="keyword">for</span> i <span class="keyword">in</span> [i**<span class="number">2</span> <span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">1</span>,<span class="number">11</span>)]:</div><div class="line">    <span class="keyword">print</span> i</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;输出结果：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="number">1</span></div><div class="line"><span class="number">4</span></div><div class="line"><span class="number">9</span></div><div class="line"><span class="number">16</span></div><div class="line"><span class="number">25</span></div><div class="line"><span class="number">36</span></div><div class="line"><span class="number">49</span></div><div class="line"><span class="number">64</span></div><div class="line"><span class="number">81</span></div><div class="line"><span class="number">100</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;说明：</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;这种写法叫做列表重写，凡是列表都可以进行重写。</p>
<h3 id="实例5：1-2-3-……-100"><a href="#实例5：1-2-3-……-100" class="headerlink" title="实例5：1+2+3+……+100="></a>实例5：1+2+3+……+100=</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="comment">#!/usr/bin/python</span></div><div class="line"></div><div class="line">sum = <span class="number">0</span></div><div class="line"><span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">1</span>,<span class="number">101</span>):</div><div class="line">    sum = sum + i     <span class="comment">#或者 sum += i</span></div><div class="line"><span class="keyword">print</span> sum</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;输出结果：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="number">5050</span></div></pre></td></tr></table></figure>
<h2 id="xrange"><a href="#xrange" class="headerlink" title="xrange"></a>xrange</h2><ul>
<li>生成一个可迭代的对象</li>
</ul>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;xrange返回的是一个对象不是一个赋值的列表</p>
<p><figure class="figure"><img src="https://github.com/hcldirgit/image/blob/master/python%E6%B5%81%E7%A8%8B%E6%8E%A7%E5%88%B6-for%E5%BA%8F%E5%88%97/02.png?raw=true" alt="images"><figcaption class="figure__caption">images</figcaption></figure></p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;但是可以对xrange这个对象进行遍历</p>
<p><figure class="figure"><img src="https://github.com/hcldirgit/image/blob/master/python%E6%B5%81%E7%A8%8B%E6%8E%A7%E5%88%B6-for%E5%BA%8F%E5%88%97/03.png?raw=true" alt="images"><figcaption class="figure__caption">images</figcaption></figure></p>
<h2 id="迭代遍历"><a href="#迭代遍历" class="headerlink" title="迭代遍历"></a>迭代遍历</h2><ul>
<li>遍历序列：将序列中各个元素取出来<ul>
<li>直接从序列取值</li>
<li>通过索引来取值</li>
</ul>
</li>
</ul>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;注：“迭代”，只重复执行一个指令。</p>
<h3 id="实例-1"><a href="#实例-1" class="headerlink" title="实例"></a>实例</h3><h4 id="实例1："><a href="#实例1：" class="headerlink" title="实例1："></a>实例1：</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="comment">#!/usr/bin/python</span></div><div class="line"></div><div class="line">fruits = [<span class="string">'banana'</span>, <span class="string">'apple'</span>,  <span class="string">'mango'</span>]</div><div class="line"><span class="keyword">for</span> fruit <span class="keyword">in</span> fruits:        </div><div class="line">   <span class="keyword">print</span> <span class="string">'当前水果 :'</span>, fruit</div><div class="line"> </div><div class="line"><span class="keyword">print</span> <span class="string">"Good bye!"</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;输出结果：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">当前水果 : banana</div><div class="line">当前水果 : apple</div><div class="line">当前水果 : mango</div><div class="line">Good bye!</div></pre></td></tr></table></figure>
<h4 id="实例2：-1"><a href="#实例2：-1" class="headerlink" title="实例2："></a>实例2：</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="comment">#!/usr/bin/python</span></div><div class="line"></div><div class="line">fruits = [<span class="string">'banana'</span>, <span class="string">'apple'</span>,  <span class="string">'mango'</span>]</div><div class="line"><span class="keyword">for</span> index <span class="keyword">in</span> range(len(fruits)):</div><div class="line">   <span class="keyword">print</span> <span class="string">'当前水果 :'</span>, fruits[index]</div><div class="line"> </div><div class="line"><span class="keyword">print</span> <span class="string">"Good bye!"</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;输出结果：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">当前水果 : banana</div><div class="line">当前水果 : apple</div><div class="line">当前水果 : mango</div><div class="line">Good bye!</div></pre></td></tr></table></figure>

	

	

</article>




	<article>
	
		<h1><a href="/2017/10/12/Python/1. Python 基础篇/1. Python 基础语法/2.2 流程控制-for 序列/13. Python for 循环语句/">Python for 循环语句</a></h1>
	
	<div class="article__infos">
		<span class="article__date">2017-10-12</span><br />
		
		
			<span class="article__tags">
			  	<a class="article__tag-link" href="/tags/Python/">Python</a>
			</span>
		
	</div>

	

	
		<h1 id="Python-for-循环语句"><a href="#Python-for-循环语句" class="headerlink" title="Python for 循环语句"></a>Python for 循环语句</h1><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Python for循环可以遍历任何序列的项目，如一个列表或者一个字符串。</p>
<h2 id="语法："><a href="#语法：" class="headerlink" title="语法："></a>语法：</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;for循环的语法格式如下：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">for</span> iterating_var <span class="keyword">in</span> sequence:</div><div class="line">   statements(s)</div></pre></td></tr></table></figure>
<h2 id="流程图："><a href="#流程图：" class="headerlink" title="流程图："></a>流程图：</h2><p><figure class="figure"><img src="https://github.com/hcldirgit/image/blob/master/python%E6%B5%81%E7%A8%8B%E6%8E%A7%E5%88%B6-for%E5%BA%8F%E5%88%97/01.jpg?raw=true" alt="images"><figcaption class="figure__caption">images</figcaption></figure></p>
<h3 id="实例"><a href="#实例" class="headerlink" title="实例"></a>实例</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="comment">#!/usr/bin/python</span></div><div class="line"><span class="comment"># -*- coding: UTF-8 -*-</span></div><div class="line"> </div><div class="line"><span class="keyword">for</span> letter <span class="keyword">in</span> <span class="string">'Python'</span>:     <span class="comment"># 第一个实例</span></div><div class="line">   <span class="keyword">print</span> <span class="string">'当前字母 :'</span>, letter</div><div class="line"> </div><div class="line">fruits = [<span class="string">'banana'</span>, <span class="string">'apple'</span>,  <span class="string">'mango'</span>]</div><div class="line"><span class="keyword">for</span> fruit <span class="keyword">in</span> fruits:        <span class="comment"># 第二个实例</span></div><div class="line">   <span class="keyword">print</span> <span class="string">'当前水果 :'</span>, fruit</div><div class="line"> </div><div class="line"><span class="keyword">print</span> <span class="string">"Good bye!"</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;以上实例输出结果:</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line">当前字母 : P</div><div class="line">当前字母 : y</div><div class="line">当前字母 : t</div><div class="line">当前字母 : h</div><div class="line">当前字母 : o</div><div class="line">当前字母 : n</div><div class="line">当前水果 : banana</div><div class="line">当前水果 : apple</div><div class="line">当前水果 : mango</div><div class="line">Good bye!</div></pre></td></tr></table></figure>
<h2 id="通过序列索引迭代"><a href="#通过序列索引迭代" class="headerlink" title="通过序列索引迭代"></a>通过序列索引迭代</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;另外一种执行循环的遍历方式是通过索引，如下实例：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="comment">#!/usr/bin/python</span></div><div class="line"><span class="comment"># -*- coding: UTF-8 -*-</span></div><div class="line"> </div><div class="line">fruits = [<span class="string">'banana'</span>, <span class="string">'apple'</span>,  <span class="string">'mango'</span>]</div><div class="line"><span class="keyword">for</span> index <span class="keyword">in</span> range(len(fruits)):</div><div class="line">   <span class="keyword">print</span> <span class="string">'当前水果 :'</span>, fruits[index]</div><div class="line"> </div><div class="line"><span class="keyword">print</span> <span class="string">"Good bye!"</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;以上实例输出结果：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">当前水果 : banana</div><div class="line">当前水果 : apple</div><div class="line">当前水果 : mango</div><div class="line">Good bye!</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;以上实例我们使用了内置函数 len() 和 range(),函数 len() 返回列表的长度，即元素的个数。 range返回一个序列的数。</p>
<h2 id="循环使用-else-语句"><a href="#循环使用-else-语句" class="headerlink" title="循环使用 else 语句"></a>循环使用 else 语句</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在 python 中，for … else 表示这样的意思，for 中的语句和普通的没有区别，else 中的语句会在循环正常执行完（即 for 不是通过 break 跳出而中断的）的情况下执行，while … else 也是一样。</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="comment">#!/usr/bin/python</span></div><div class="line"><span class="comment"># -*- coding: UTF-8 -*-</span></div><div class="line"> </div><div class="line"><span class="keyword">for</span> num <span class="keyword">in</span> range(<span class="number">10</span>,<span class="number">20</span>):  <span class="comment"># 迭代 10 到 20 之间的数字</span></div><div class="line">   <span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">2</span>,num): <span class="comment"># 根据因子迭代</span></div><div class="line">      <span class="keyword">if</span> num%i == <span class="number">0</span>:      <span class="comment"># 确定第一个因子</span></div><div class="line">         j=num/i          <span class="comment"># 计算第二个因子</span></div><div class="line">         <span class="keyword">print</span> <span class="string">'%d 等于 %d * %d'</span> % (num,i,j)</div><div class="line">         <span class="keyword">break</span>            <span class="comment"># 跳出当前循环</span></div><div class="line">   <span class="keyword">else</span>:                  <span class="comment"># 循环的 else 部分</span></div><div class="line">      <span class="keyword">print</span> num, <span class="string">'是一个质数'</span></div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;以上实例输出结果：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="number">10</span> 等于 <span class="number">2</span> * <span class="number">5</span></div><div class="line"><span class="number">11</span> 是一个质数</div><div class="line"><span class="number">12</span> 等于 <span class="number">2</span> * <span class="number">6</span></div><div class="line"><span class="number">13</span> 是一个质数</div><div class="line"><span class="number">14</span> 等于 <span class="number">2</span> * <span class="number">7</span></div><div class="line"><span class="number">15</span> 等于 <span class="number">3</span> * <span class="number">5</span></div><div class="line"><span class="number">16</span> 等于 <span class="number">2</span> * <span class="number">8</span></div><div class="line"><span class="number">17</span> 是一个质数</div><div class="line"><span class="number">18</span> 等于 <span class="number">2</span> * <span class="number">9</span></div><div class="line"><span class="number">19</span> 是一个质数</div></pre></td></tr></table></figure>
	

	

</article>





	<span class="different-posts">📖 <a href="/page/19">more posts</a> 📖</span>



	</main>

	<footer class="footer">
	<div class="footer-content">
		
	      <div class="footer__element">
	<p>Hi there, <br />welcome to my Blog glad you found it. Have a look around, will you?</p>
</div>

	    
	      <div class="footer__element">
	<h5>Check out</h5>
	<ul class="footer-links">
		<li class="footer-links__link"><a href="/archives">Archive</a></li>
		
		  <li class="footer-links__link"><a href="/atom.xml">RSS</a></li>
	    
		<li class="footer-links__link"><a href="/about">about page</a></li>
		<li class="footer-links__link"><a href="/tags">Tags</a></li>
		<li class="footer-links__link"><a href="/categories">Categories</a></li>
	</ul>
</div>

	    

		<div class="footer-credit">
			<span>© 2017 失落的乐章 | Powered by <a href="https://hexo.io/">Hexo</a> | Theme <a href="https://github.com/HoverBaum/meilidu-hexo">MeiliDu</a></span>
		</div>

	</div>


</footer>



</body>

</html>
